Skip to content

Commit e7c9033

Browse files
authored
Add Python 3.13, remove 3.8 (#1061)
* Drop Python 3.8, add 3.13 * Update dev tools; apply safe fixes * Apply usafe ruff auto-fixes * Fix the rest linter errors * Fix typos * Downgrade doc deps to be compatible with 3.9 * Rewrite gen-ssl-certs.sh, add keyUsage
1 parent 608ab24 commit e7c9033

Some content is hidden

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

56 files changed

+411
-532
lines changed

.github/workflows/publish.yml

+14-14
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
- uses: actions/checkout@v2
1616
- uses: actions/setup-python@v2
1717
with:
18-
python-version: "3.8"
18+
python-version: "3.9"
1919
- name: Prepare C files to include
2020
run: |
2121
python -m pip install --upgrade pip build
@@ -52,7 +52,7 @@ jobs:
5252
- uses: actions/checkout@v2
5353
- uses: actions/setup-python@v2
5454
with:
55-
python-version: "3.8"
55+
python-version: "3.9"
5656
- name: Set up QEMU
5757
if: ${{ matrix.arch == 'aarch64' }}
5858
uses: docker/setup-qemu-action@v1
@@ -82,10 +82,8 @@ jobs:
8282

8383
strategy:
8484
matrix:
85-
python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
85+
python: ["3.9", "3.10", "3.11", "3.12", "3.13"]
8686
include:
87-
- python: "3.8"
88-
aiokafka_whl: dist/aiokafka-*-cp38-cp38-win_amd64.whl
8987
- python: "3.9"
9088
aiokafka_whl: dist/aiokafka-*-cp39-cp39-win_amd64.whl
9189
- python: "3.10"
@@ -94,6 +92,8 @@ jobs:
9492
aiokafka_whl: dist/aiokafka-*-cp311-cp311-win_amd64.whl
9593
- python: "3.12"
9694
aiokafka_whl: dist/aiokafka-*-cp312-cp312-win_amd64.whl
95+
- python: "3.13"
96+
aiokafka_whl: dist/aiokafka-*-cp313-cp313-win_amd64.whl
9797

9898
steps:
9999
- uses: actions/checkout@v2
@@ -127,10 +127,8 @@ jobs:
127127

128128
strategy:
129129
matrix:
130-
python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
130+
python: ["3.9", "3.10", "3.11", "3.12", "3.13"]
131131
include:
132-
- python: "3.8"
133-
aiokafka_whl: dist/aiokafka-*-cp38-cp38-macosx_*_x86_64.whl
134132
- python: "3.9"
135133
aiokafka_whl: dist/aiokafka-*-cp39-cp39-macosx_*_x86_64.whl
136134
- python: "3.10"
@@ -139,6 +137,8 @@ jobs:
139137
aiokafka_whl: dist/aiokafka-*-cp311-cp311-macosx_*_x86_64.whl
140138
- python: "3.12"
141139
aiokafka_whl: dist/aiokafka-*-cp312-cp312-macosx_*_x86_64.whl
140+
- python: "3.13"
141+
aiokafka_whl: dist/aiokafka-*-cp313-cp313-macosx_*_x86_64.whl
142142

143143
steps:
144144
- uses: actions/checkout@v2
@@ -170,10 +170,8 @@ jobs:
170170

171171
strategy:
172172
matrix:
173-
python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
173+
python: ["3.9", "3.10", "3.11", "3.12", "3.13"]
174174
include:
175-
- python: "3.8"
176-
aiokafka_whl: dist/aiokafka-*-cp38-cp38-macosx_*_arm64.whl
177175
- python: "3.9"
178176
aiokafka_whl: dist/aiokafka-*-cp39-cp39-macosx_*_arm64.whl
179177
- python: "3.10"
@@ -182,6 +180,8 @@ jobs:
182180
aiokafka_whl: dist/aiokafka-*-cp311-cp311-macosx_*_arm64.whl
183181
- python: "3.12"
184182
aiokafka_whl: dist/aiokafka-*-cp312-cp312-macosx_*_arm64.whl
183+
- python: "3.13"
184+
aiokafka_whl: dist/aiokafka-*-cp313-cp313-macosx_*_arm64.whl
185185

186186
steps:
187187
- uses: actions/checkout@v2
@@ -213,10 +213,8 @@ jobs:
213213

214214
strategy:
215215
matrix:
216-
python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
216+
python: ["3.9", "3.10", "3.11", "3.12", "3.13"]
217217
include:
218-
- python: "3.8"
219-
aiokafka_whl: dist/aiokafka-*-cp38-cp38-manylinux*_x86_64.whl
220218
- python: "3.9"
221219
aiokafka_whl: dist/aiokafka-*-cp39-cp39-manylinux*_x86_64.whl
222220
- python: "3.10"
@@ -225,6 +223,8 @@ jobs:
225223
aiokafka_whl: dist/aiokafka-*-cp311-cp311-manylinux*_x86_64.whl
226224
- python: "3.12"
227225
aiokafka_whl: dist/aiokafka-*-cp312-cp312-manylinux*_x86_64.whl
226+
- python: "3.13"
227+
aiokafka_whl: dist/aiokafka-*-cp313-cp313-manylinux*_x86_64.whl
228228

229229
steps:
230230
- uses: actions/checkout@v2

.github/workflows/tests.yml

+17-17
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ jobs:
7373

7474
strategy:
7575
matrix:
76-
python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
76+
python: ["3.9", "3.10", "3.11", "3.12", "3.13"]
7777

7878
steps:
7979
- uses: actions/checkout@v2
@@ -141,7 +141,7 @@ jobs:
141141

142142
strategy:
143143
matrix:
144-
python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
144+
python: ["3.9", "3.10", "3.11", "3.12", "3.13"]
145145

146146
steps:
147147
- uses: actions/checkout@v2
@@ -210,14 +210,11 @@ jobs:
210210
strategy:
211211
matrix:
212212
include:
213-
- python: "3.12"
213+
- python: "3.13"
214214
kafka: "2.8.1"
215215
scala: "2.13"
216216

217217
# Older python versions against latest broker
218-
- python: "3.8"
219-
kafka: "2.8.1"
220-
scala: "2.13"
221218
- python: "3.9"
222219
kafka: "2.8.1"
223220
scala: "2.13"
@@ -227,39 +224,42 @@ jobs:
227224
- python: "3.11"
228225
kafka: "2.8.1"
229226
scala: "2.13"
227+
- python: "3.12"
228+
kafka: "2.8.1"
229+
scala: "2.13"
230230

231231
# Older brokers against latest python version
232-
- python: "3.12"
232+
- python: "3.13"
233233
kafka: "0.9.0.1"
234234
scala: "2.11"
235-
- python: "3.12"
235+
- python: "3.13"
236236
kafka: "0.10.2.1"
237237
scala: "2.11"
238-
- python: "3.12"
238+
- python: "3.13"
239239
kafka: "0.11.0.3"
240240
scala: "2.12"
241-
- python: "3.12"
241+
- python: "3.13"
242242
kafka: "1.1.1"
243243
scala: "2.12"
244-
- python: "3.12"
244+
- python: "3.13"
245245
kafka: "2.1.1"
246246
scala: "2.12"
247-
- python: "3.12"
247+
- python: "3.13"
248248
kafka: "2.2.2"
249249
scala: "2.12"
250-
- python: "3.12"
250+
- python: "3.13"
251251
kafka: "2.3.1"
252252
scala: "2.12"
253-
- python: "3.12"
253+
- python: "3.13"
254254
kafka: "2.4.1"
255255
scala: "2.12"
256-
- python: "3.12"
256+
- python: "3.13"
257257
kafka: "2.5.1"
258258
scala: "2.12"
259-
- python: "3.12"
259+
- python: "3.13"
260260
kafka: "2.6.3"
261261
scala: "2.12"
262-
- python: "3.12"
262+
- python: "3.13"
263263
kafka: "2.7.2"
264264
scala: "2.13"
265265
fail-fast: false

aiokafka/admin/client.py

+28-27
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import asyncio
22
import logging
33
from collections import defaultdict
4+
from collections.abc import Sequence
45
from ssl import SSLContext
5-
from typing import Any, Dict, List, Optional, Sequence, Tuple, Type, Union
6+
from typing import Any, Optional, Union
67

78
import async_timeout
89

@@ -88,7 +89,7 @@ def __init__(
8889
self,
8990
*,
9091
loop=None,
91-
bootstrap_servers: Union[str, List[str]] = "localhost",
92+
bootstrap_servers: Union[str, list[str]] = "localhost",
9293
client_id: str = "aiokafka-" + __version__,
9394
request_timeout_ms: int = 40000,
9495
connections_max_idle_ms: int = 540000,
@@ -159,7 +160,7 @@ async def start(self):
159160
log.debug("AIOKafkaAdminClient started")
160161
self._started = True
161162

162-
def _matching_api_version(self, operation: Sequence[Type[Request]]) -> int:
163+
def _matching_api_version(self, operation: Sequence[type[Request]]) -> int:
163164
"""Find the latest version of the protocol operation
164165
supported by both this library and the broker.
165166
@@ -225,7 +226,7 @@ def _convert_new_topic_request(new_topic):
225226

226227
async def create_topics(
227228
self,
228-
new_topics: List[NewTopic],
229+
new_topics: list[NewTopic],
229230
timeout_ms: Optional[int] = None,
230231
validate_only: bool = False,
231232
) -> Response:
@@ -267,7 +268,7 @@ async def create_topics(
267268

268269
async def delete_topics(
269270
self,
270-
topics: List[str],
271+
topics: list[str],
271272
timeout_ms: Optional[int] = None,
272273
) -> Response:
273274
"""Delete topics from the cluster.
@@ -284,7 +285,7 @@ async def delete_topics(
284285

285286
async def _get_cluster_metadata(
286287
self,
287-
topics: Optional[List[str]] = None,
288+
topics: Optional[list[str]] = None,
288289
) -> Response:
289290
"""
290291
Retrieve cluster metadata
@@ -295,30 +296,30 @@ async def _get_cluster_metadata(
295296
request = req_cls(topics=topics)
296297
return await self._send_request(request)
297298

298-
async def list_topics(self) -> List[str]:
299+
async def list_topics(self) -> list[str]:
299300
metadata = await self._get_cluster_metadata(topics=None)
300301
obj = metadata.to_object()
301302
return [t["topic"] for t in obj["topics"]]
302303

303304
async def describe_topics(
304305
self,
305-
topics: Optional[List[str]] = None,
306-
) -> List[Any]:
306+
topics: Optional[list[str]] = None,
307+
) -> list[Any]:
307308
metadata = await self._get_cluster_metadata(topics=topics)
308309
obj = metadata.to_object()
309310
return obj["topics"]
310311

311-
async def describe_cluster(self) -> Dict[str, Any]:
312+
async def describe_cluster(self) -> dict[str, Any]:
312313
metadata = await self._get_cluster_metadata()
313314
obj = metadata.to_object()
314315
obj.pop("topics") # We have 'describe_topics' for this
315316
return obj
316317

317318
async def describe_configs(
318319
self,
319-
config_resources: List[ConfigResource],
320+
config_resources: list[ConfigResource],
320321
include_synonyms: bool = False,
321-
) -> List[Response]:
322+
) -> list[Response]:
322323
"""Fetch configuration parameters for one or more Kafka resources.
323324
324325
:param config_resources: An list of ConfigResource objects.
@@ -360,8 +361,8 @@ async def describe_configs(
360361
return await asyncio.gather(*futures)
361362

362363
async def alter_configs(
363-
self, config_resources: List[ConfigResource]
364-
) -> List[Response]:
364+
self, config_resources: list[ConfigResource]
365+
) -> list[Response]:
365366
"""Alter configuration parameters of one or more Kafka resources.
366367
:param config_resources: A list of ConfigResource objects.
367368
:return: Appropriate version of AlterConfigsResponse class.
@@ -398,9 +399,9 @@ def _convert_alter_config_resource_request(config_resource):
398399
@classmethod
399400
def _convert_config_resources(
400401
cls,
401-
config_resources: List[ConfigResource],
402+
config_resources: list[ConfigResource],
402403
op_type: str = "describe",
403-
) -> Tuple[Dict[int, Any], List[Any]]:
404+
) -> tuple[dict[int, Any], list[Any]]:
404405
broker_resources = defaultdict(list)
405406
topic_resources = []
406407
if op_type == "describe":
@@ -416,15 +417,15 @@ def _convert_config_resources(
416417
return broker_resources, topic_resources
417418

418419
@staticmethod
419-
def _convert_topic_partitions(topic_partitions: Dict[str, NewPartitions]):
420+
def _convert_topic_partitions(topic_partitions: dict[str, NewPartitions]):
420421
return [
421422
(topic_name, (new_part.total_count, new_part.new_assignments))
422423
for topic_name, new_part in topic_partitions.items()
423424
]
424425

425426
async def create_partitions(
426427
self,
427-
topic_partitions: Dict[str, NewPartitions],
428+
topic_partitions: dict[str, NewPartitions],
428429
timeout_ms: Optional[int] = None,
429430
validate_only: bool = False,
430431
) -> Response:
@@ -455,10 +456,10 @@ async def create_partitions(
455456

456457
async def describe_consumer_groups(
457458
self,
458-
group_ids: List[str],
459+
group_ids: list[str],
459460
group_coordinator_id: Optional[int] = None,
460461
include_authorized_operations: bool = False,
461-
) -> List[Response]:
462+
) -> list[Response]:
462463
"""Describe a set of consumer groups.
463464
464465
Any errors are immediately raised.
@@ -508,8 +509,8 @@ async def describe_consumer_groups(
508509

509510
async def list_consumer_groups(
510511
self,
511-
broker_ids: Optional[List[int]] = None,
512-
) -> List[Tuple[Any, ...]]:
512+
broker_ids: Optional[list[int]] = None,
513+
) -> list[tuple[Any, ...]]:
513514
"""List all consumer groups known to the cluster.
514515
515516
This returns a list of Consumer Group tuples. The tuples are
@@ -578,8 +579,8 @@ async def list_consumer_group_offsets(
578579
self,
579580
group_id: str,
580581
group_coordinator_id: Optional[int] = None,
581-
partitions: Optional[List[TopicPartition]] = None,
582-
) -> Dict[TopicPartition, OffsetAndMetadata]:
582+
partitions: Optional[list[TopicPartition]] = None,
583+
) -> dict[TopicPartition, OffsetAndMetadata]:
583584
"""Fetch Consumer Offsets for a single consumer group.
584585
585586
Note:
@@ -636,9 +637,9 @@ async def list_consumer_group_offsets(
636637

637638
async def delete_records(
638639
self,
639-
records_to_delete: Dict[TopicPartition, RecordsToDelete],
640+
records_to_delete: dict[TopicPartition, RecordsToDelete],
640641
timeout_ms: Optional[int] = None,
641-
) -> Dict[TopicPartition, int]:
642+
) -> dict[TopicPartition, int]:
642643
"""Delete records from partitions.
643644
644645
:param records_to_delete: A map of RecordsToDelete for each TopicPartition
@@ -681,7 +682,7 @@ async def delete_records(
681682

682683
@staticmethod
683684
def _convert_records_to_delete(
684-
records_to_delete: Dict[str, List[Tuple[int, RecordsToDelete]]],
685+
records_to_delete: dict[str, list[tuple[int, RecordsToDelete]]],
685686
):
686687
return [
687688
(topic, [(partition, rec.before_offset) for partition, rec in records])

aiokafka/client.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ def _get_conn_lock(self):
174174
return self._get_conn_lock_value
175175

176176
def __repr__(self):
177-
return "<AIOKafkaClient client_id=%s>" % self._client_id
177+
return f"<AIOKafkaClient client_id={self._client_id}>"
178178

179179
@property
180180
def api_version(self):
@@ -483,9 +483,7 @@ async def _get_conn(self, node_id, *, group=ConnectionGroup.DEFAULT, no_hint=Fal
483483

484484
async def ready(self, node_id, *, group=ConnectionGroup.DEFAULT):
485485
conn = await self._get_conn(node_id, group=group)
486-
if conn is None:
487-
return False
488-
return True
486+
return conn is not None
489487

490488
async def send(self, node_id, request, *, group=ConnectionGroup.DEFAULT):
491489
"""Send a request to a specific node.

0 commit comments

Comments
 (0)