Skip to content

Commit 7b7c4ff

Browse files
authored
Build wheels for Python 3.14 (#1140)
* Build for Python 3.14 * Update dependencies; fix linting errors * Use 3.11 for cibuildwheel * Deprecated macos-13 -> macos-15-intel
1 parent 9f9161e commit 7b7c4ff

35 files changed

+139
-136
lines changed

.github/workflows/publish.yml

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
arch: x86_64
4343
- os: ubuntu-latest
4444
arch: aarch64
45-
- os: macos-13
45+
- os: macos-15-intel
4646
arch: x86_64
4747
- os: macos-latest
4848
arch: arm64
@@ -52,14 +52,15 @@ jobs:
5252
- uses: actions/checkout@v4
5353
- uses: actions/setup-python@v5
5454
with:
55-
python-version: "3.10"
55+
# cibuildwheel requires 3.11+
56+
python-version: "3.11"
5657
- name: Set up QEMU
5758
if: ${{ matrix.arch == 'aarch64' }}
5859
uses: docker/setup-qemu-action@v3
5960
- name: Build wheels
6061
env:
6162
CIBW_ARCHS_LINUX: ${{matrix.arch}}
62-
CIBW_BUILD: cp39-* cp310-* cp311-* cp312-* cp313-*
63+
CIBW_BUILD: cp310-* cp311-* cp312-* cp313-* cp314-*
6364
CIBW_SKIP: '*-musllinux*'
6465
CIBW_BEFORE_BUILD_LINUX: pip install -r requirements-cython.txt && yum install -y zlib-devel
6566
# On windows and mac we should have z library preinstalled
@@ -82,7 +83,7 @@ jobs:
8283

8384
strategy:
8485
matrix:
85-
python: ["3.10", "3.11", "3.12", "3.13"]
86+
python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
8687
include:
8788
- python: "3.10"
8889
aiokafka_whl: dist/aiokafka-*-cp310-cp310-win_amd64.whl
@@ -92,6 +93,8 @@ jobs:
9293
aiokafka_whl: dist/aiokafka-*-cp312-cp312-win_amd64.whl
9394
- python: "3.13"
9495
aiokafka_whl: dist/aiokafka-*-cp313-cp313-win_amd64.whl
96+
- python: "3.14"
97+
aiokafka_whl: dist/aiokafka-*-cp314-cp314-win_amd64.whl
9598

9699
steps:
97100
- uses: actions/checkout@v4
@@ -121,11 +124,11 @@ jobs:
121124

122125
test-wheels-mac:
123126
needs: [package-source, package-wheel]
124-
runs-on: macos-13
127+
runs-on: macos-15-intel
125128

126129
strategy:
127130
matrix:
128-
python: ["3.10", "3.11", "3.12", "3.13"]
131+
python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
129132
include:
130133
- python: "3.10"
131134
aiokafka_whl: dist/aiokafka-*-cp310-cp310-macosx_*_x86_64.whl
@@ -135,13 +138,15 @@ jobs:
135138
aiokafka_whl: dist/aiokafka-*-cp312-cp312-macosx_*_x86_64.whl
136139
- python: "3.13"
137140
aiokafka_whl: dist/aiokafka-*-cp313-cp313-macosx_*_x86_64.whl
141+
- python: "3.14"
142+
aiokafka_whl: dist/aiokafka-*-cp314-cp314-macosx_*_x86_64.whl
138143

139144
steps:
140145
- uses: actions/checkout@v4
141146
- name: Download distributions
142147
uses: actions/download-artifact@v4
143148
with:
144-
name: dist-macos-13-x86_64
149+
name: dist-macos-15-intel-x86_64
145150
path: dist/
146151
- name: Set up Python
147152
uses: actions/setup-python@v5
@@ -166,7 +171,7 @@ jobs:
166171

167172
strategy:
168173
matrix:
169-
python: ["3.10", "3.11", "3.12", "3.13"]
174+
python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
170175
include:
171176
- python: "3.10"
172177
aiokafka_whl: dist/aiokafka-*-cp310-cp310-macosx_*_arm64.whl
@@ -176,6 +181,8 @@ jobs:
176181
aiokafka_whl: dist/aiokafka-*-cp312-cp312-macosx_*_arm64.whl
177182
- python: "3.13"
178183
aiokafka_whl: dist/aiokafka-*-cp313-cp313-macosx_*_arm64.whl
184+
- python: "3.14"
185+
aiokafka_whl: dist/aiokafka-*-cp314-cp314-macosx_*_arm64.whl
179186

180187
steps:
181188
- uses: actions/checkout@v4
@@ -207,7 +214,7 @@ jobs:
207214

208215
strategy:
209216
matrix:
210-
python: ["3.10", "3.11", "3.12", "3.13"]
217+
python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
211218
include:
212219
- python: "3.10"
213220
aiokafka_whl: dist/aiokafka-*-cp310-cp310-manylinux*_x86_64.whl
@@ -217,6 +224,8 @@ jobs:
217224
aiokafka_whl: dist/aiokafka-*-cp312-cp312-manylinux*_x86_64.whl
218225
- python: "3.13"
219226
aiokafka_whl: dist/aiokafka-*-cp313-cp313-manylinux*_x86_64.whl
227+
- python: "3.14"
228+
aiokafka_whl: dist/aiokafka-*-cp314-cp314-manylinux*_x86_64.whl
220229

221230
steps:
222231
- uses: actions/checkout@v4
@@ -256,8 +265,6 @@ jobs:
256265
strategy:
257266
matrix:
258267
include:
259-
- pyver: cp39-cp39
260-
aiokafka_whl: dist/aiokafka-*-cp39-cp39-manylinux*_aarch64.whl
261268
- pyver: cp310-cp310
262269
aiokafka_whl: dist/aiokafka-*-cp310-cp310-manylinux*_aarch64.whl
263270
- pyver: cp311-cp311
@@ -266,6 +273,8 @@ jobs:
266273
aiokafka_whl: dist/aiokafka-*-cp312-cp312-manylinux*_aarch64.whl
267274
- pyver: cp313-cp313
268275
aiokafka_whl: dist/aiokafka-*-cp313-cp313-manylinux*_aarch64.whl
276+
- pyver: cp314-cp314
277+
aiokafka_whl: dist/aiokafka-*-cp314-cp314-manylinux*_aarch64.whl
269278

270279
steps:
271280
- uses: actions/checkout@v4

.github/workflows/tests.yml

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ jobs:
7373

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

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

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

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

@@ -224,33 +224,36 @@ jobs:
224224
- python: "3.12"
225225
kafka: "2.8.1"
226226
scala: "2.13"
227+
- python: "3.13"
228+
kafka: "2.8.1"
229+
scala: "2.13"
227230

228231
# Older brokers against latest python version
229-
- python: "3.13"
232+
- python: "3.14"
230233
kafka: "0.11.0.3"
231234
scala: "2.12"
232-
- python: "3.13"
235+
- python: "3.14"
233236
kafka: "1.1.1"
234237
scala: "2.12"
235-
- python: "3.13"
238+
- python: "3.14"
236239
kafka: "2.1.1"
237240
scala: "2.12"
238-
- python: "3.13"
241+
- python: "3.14"
239242
kafka: "2.2.2"
240243
scala: "2.12"
241-
- python: "3.13"
244+
- python: "3.14"
242245
kafka: "2.3.1"
243246
scala: "2.12"
244-
- python: "3.13"
247+
- python: "3.14"
245248
kafka: "2.4.1"
246249
scala: "2.12"
247-
- python: "3.13"
250+
- python: "3.14"
248251
kafka: "2.5.1"
249252
scala: "2.12"
250-
- python: "3.13"
253+
- python: "3.14"
251254
kafka: "2.6.3"
252255
scala: "2.12"
253-
- python: "3.13"
256+
- python: "3.14"
254257
kafka: "2.7.2"
255258
scala: "2.13"
256259
fail-fast: false

aiokafka/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
TopicPartition,
1313
)
1414

15-
__all__ = [
15+
__all__ = [ # noqa: RUF022
1616
# Clients API
1717
"AIOKafkaProducer",
1818
"AIOKafkaConsumer",

aiokafka/client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,9 @@ async def close(self):
179179

180180
async def bootstrap(self):
181181
"""Try to to bootstrap initial cluster metadata"""
182-
assert (
183-
self._loop is get_running_loop()
184-
), "Please create objects with the same loop as running with"
182+
assert self._loop is get_running_loop(), (
183+
"Please create objects with the same loop as running with"
184+
)
185185

186186
for host, port, _ in self.hosts:
187187
log.debug("Attempting to bootstrap via node at %s:%s", host, port)

aiokafka/cluster.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,7 @@ def add_coordinator(self, node_id, host, port, rack=None, *, purpose):
390390
self._coordinator_by_key[purpose] = node_id
391391

392392
def __str__(self):
393-
return "ClusterMetadata(brokers: %d, topics: %d, groups: %d)" % (
394-
len(self._brokers),
395-
len(self._partitions),
396-
len(self._groups),
393+
return (
394+
f"ClusterMetadata(brokers: {len(self._brokers)}, topics: "
395+
f"{len(self._partitions)}, groups: {len(self._groups)})"
397396
)

aiokafka/conn.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ def __init__(
138138
"sasl_oauth_token_provider needs to be"
139139
" provided implementing aiokafka.abc.AbstractTokenProvider"
140140
)
141-
assert callable(
142-
getattr(sasl_oauth_token_provider, "token", None)
143-
), "sasl_oauth_token_provider must implement method #token()"
141+
assert callable(getattr(sasl_oauth_token_provider, "token", None)), (
142+
"sasl_oauth_token_provider must implement method #token()"
143+
)
144144

145145
self._loop = loop
146146
self._host = host

aiokafka/consumer/consumer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,9 +357,9 @@ async def start(self):
357357
* Wait for possible topic autocreation
358358
* Join group if ``group_id`` provided
359359
"""
360-
assert (
361-
self._loop is get_running_loop()
362-
), "Please create objects with the same loop as running with"
360+
assert self._loop is get_running_loop(), (
361+
"Please create objects with the same loop as running with"
362+
)
363363
assert self._fetcher is None, "Did you call `start` twice?"
364364
await self._client.bootstrap()
365365
await self._wait_topics()

aiokafka/consumer/fetcher.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,9 @@ def _unpack_records(self):
225225
self._consume_aborted_up_to(next_batch.base_offset)
226226

227227
if (
228-
next_batch.is_control_batch # fmt: skip
228+
next_batch.is_control_batch
229229
and self._contains_abort_marker(next_batch)
230-
):
230+
): # fmt: skip
231231
# Using `discard` instead of `remove`, because Kafka
232232
# may return an abort marker for an otherwise empty
233233
# topic-partition.
@@ -977,9 +977,9 @@ async def _proc_offset_request(self, node_id, topic_data):
977977
if error_type is Errors.NoError:
978978
if response.API_VERSION == 0:
979979
offsets = partition_info[0]
980-
assert (
981-
len(offsets) <= 1
982-
), "Expected OffsetResponse with one offset"
980+
assert len(offsets) <= 1, (
981+
"Expected OffsetResponse with one offset"
982+
)
983983
if offsets:
984984
offset = offsets[0]
985985
log.debug(

aiokafka/consumer/group_coordinator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ async def _perform_assignment(self, response: Response):
435435
all_subscribed_topics = set()
436436
for member in members:
437437
if response.API_VERSION == 5:
438-
member_id, group_instance_id, metadata_bytes = member
438+
member_id, _group_instance_id, metadata_bytes = member
439439
else:
440440
member_id, metadata_bytes = member
441441
metadata = ConsumerProtocol.METADATA.decode(metadata_bytes)
@@ -675,7 +675,7 @@ async def __coordination_routine(self):
675675
if self._commit_refresh_task:
676676
futures.append(self._commit_refresh_task)
677677

678-
done, _ = await asyncio.wait(
678+
await asyncio.wait(
679679
futures, timeout=wait_timeout, return_when=asyncio.FIRST_COMPLETED
680680
)
681681

aiokafka/consumer/subscription_state.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,9 @@ def assignment(self):
338338

339339
def _assign(self, topic_partitions: Iterable[TopicPartition]):
340340
for tp in topic_partitions:
341-
assert (
342-
tp.topic in self._topics
343-
), f"Received an assignment for unsubscribed topic: {tp}"
341+
assert tp.topic in self._topics, (
342+
f"Received an assignment for unsubscribed topic: {tp}"
343+
)
344344

345345
if self._assignment is not None:
346346
self._assignment._unassign()

0 commit comments

Comments
 (0)