Upgrade Python version to 3.10-3.14

This commit is contained in:
Josh Wu
2025-10-21 20:00:10 +08:00
parent 0fa517a4f6
commit 5431941fe7
11 changed files with 20 additions and 42 deletions

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13.0"]
python-version: ["3.10", "3.11", "3.12", "3.13.0", "3.14"]
fail-fast: false
steps:

View File

@@ -18,7 +18,7 @@ jobs:
strategy:
matrix:
os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
fail-fast: false
steps:
@@ -48,7 +48,8 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
# Rust runtime doesn't support 3.14 yet.
python-version: ["3.10", "3.11", "3.12", "3.13"]
rust-version: [ "1.80.0", "stable" ]
fail-fast: false
steps:

View File

@@ -742,10 +742,9 @@ async def run_receive(
]
packet_stats = [0, 0]
async with contextlib.AsyncExitStack() as stack:
audio_output = await audio_io.create_audio_output(output)
# This try should be replaced with contextlib.aclosing() when python 3.9 is no
# longer needed.
try:
stack.push_async_callback(audio_output.aclose)
await audio_output.open(
audio_io.PcmFormat(
audio_io.PcmFormat.Endianness.LITTLE,
@@ -793,8 +792,6 @@ async def run_receive(
terminated = asyncio.Event()
big_sync.on(big_sync.Event.TERMINATION, lambda _: terminated.set())
await terminated.wait()
finally:
await audio_output.aclose()
async def run_transmit(
@@ -891,11 +888,10 @@ async def run_transmit(
print('Start Periodic Advertising')
await advertising_set.start_periodic()
async with contextlib.AsyncExitStack() as stack:
audio_input = await audio_io.create_audio_input(input, input_format)
pcm_format = await audio_input.open()
# This try should be replaced with contextlib.aclosing() when python 3.9 is no
# longer needed.
try:
stack.push_async_callback(audio_input.aclose)
if pcm_format.channels != 2:
print("Only 2 channels PCM configurations are supported")
return
@@ -967,8 +963,6 @@ async def run_transmit(
await iso_queues[1].write(lc3_frame[mid:])
frame_count += 1
finally:
await audio_input.aclose()
def run_async(async_command: Coroutine) -> None:

View File

@@ -19,13 +19,13 @@ from __future__ import annotations
import abc
import asyncio
import concurrent.futures
import dataclasses
import enum
import logging
import pathlib
import sys
import wave
from concurrent.futures import ThreadPoolExecutor
from typing import TYPE_CHECKING, AsyncGenerator, BinaryIO
from bumble.colors import color
@@ -176,7 +176,7 @@ class ThreadedAudioOutput(AudioOutput):
"""
def __init__(self) -> None:
self._thread_pool = ThreadPoolExecutor(1)
self._thread_pool = concurrent.futures.ThreadPoolExecutor(1)
self._pcm_samples: asyncio.Queue[bytes] = asyncio.Queue()
self._write_task = asyncio.create_task(self._write_loop())
@@ -405,7 +405,7 @@ class ThreadedAudioInput(AudioInput):
"""Base class for AudioInput implementation where reading samples may block."""
def __init__(self) -> None:
self._thread_pool = ThreadPoolExecutor(1)
self._thread_pool = concurrent.futures.ThreadPoolExecutor(1)
self._pcm_samples: asyncio.Queue[bytes] = asyncio.Queue()
@abc.abstractmethod

View File

@@ -2374,11 +2374,7 @@ class Device(utils.CompositeEventEmitter):
hci.Address.ANY: []
} # Futures, by BD address OR [Futures] for hci.Address.ANY
# In Python <= 3.9 + Rust Runtime, asyncio.Lock cannot be properly initiated.
if sys.version_info >= (3, 10):
self._cis_lock = asyncio.Lock()
else:
self._cis_lock = AsyncExitStack()
# Own address type cache
self.connect_own_address_type = None

View File

@@ -241,10 +241,6 @@ def cancel_on_event(
return
msg = f'abort: {event} event occurred.'
if isinstance(future, asyncio.Task):
# python < 3.9 does not support passing a message on `Task.cancel`
if sys.version_info < (3, 9, 0):
future.cancel()
else:
future.cancel(msg)
else:
future.set_exception(asyncio.CancelledError(msg))

View File

@@ -3,7 +3,7 @@ GETTING STARTED WITH BUMBLE
# Prerequisites
You need Python 3.9 or above.
You need Python 3.10 or above.
Visit the [Python site](https://www.python.org/) for instructions on how to install Python
for your platform.
Throughout the documentation, when shell commands are shown, it is assumed that you can

View File

@@ -31,7 +31,7 @@ Some of the configurations that may be useful:
See the [use cases page](use_cases/index.md) for more use cases.
The project is implemented in Python (Python >= 3.9 is required). A number of APIs for functionality that is inherently I/O bound is implemented in terms of python coroutines with async IO. This means that all of the concurrent tasks run in the same thread, which makes everything much simpler and more predictable.
The project is implemented in Python (Python >= 3.10 is required). A number of APIs for functionality that is inherently I/O bound is implemented in terms of python coroutines with async IO. This means that all of the concurrent tasks run in the same thread, which makes everything much simpler and more predictable.
![layers](images/bumble_layers.svg)

View File

@@ -1,7 +1,7 @@
PLATFORMS
=========
Most of the code included in the project should run on any platform that supports Python >= 3.9. Not all features are supported on all platforms (for example, USB dongle support is only available on platforms where the python USB library is functional).
Most of the code included in the project should run on any platform that supports Python >= 3.10. Not all features are supported on all platforms (for example, USB dongle support is only available on platforms where the python USB library is functional).
For platform-specific information, see the following pages:

View File

@@ -1,9 +0,0 @@
name: bumble
channels:
- defaults
- conda-forge
dependencies:
- pip=23
- python=3.9
- pip:
- --editable .[development,documentation,test]

View File

@@ -10,7 +10,7 @@ readme = "README.md"
license = "Apache-2.0"
license-files = ["LICENSE"]
authors = [{ name = "Google", email = "bumble-dev@google.com" }]
requires-python = ">=3.9"
requires-python = ">=3.10"
dependencies = [
"aiohttp ~= 3.8; platform_system!='Emscripten'",
"appdirs >= 1.4; platform_system!='Emscripten'",