Skip to content

Commit 952f579

Browse files
committed
Conditional imports refactoring
Changed ------- - `build_and_test.yml` workflow_dispatch trigger added - Updated `typing_extensions` dependency platform flags - Simplified conditional imports from `typing` with alternatives from `typing_extensions` that resolves it under the hood, so we need no control it manually - Legacy `collections.abc` imports replaced with `typing_extensions` cause current required `typing_extensions>=4.7` version already supports all them - Removed redundant (legacy) imports from `__future__` - Undefined annotations fixed Added ----- - Added `_compat.py` module to simplify future support for other python implementations, like `pypy` or `circuitpython`
1 parent 6b2c390 commit 952f579

25 files changed

+144
-110
lines changed

.github/workflows/build_and_test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ on:
77
pull_request:
88
branches: [ master, develop ]
99
paths: [ 'bleak/**', 'tests/**' ]
10+
workflow_dispatch:
1011

1112
jobs:
1213
build_desktop:

CHANGELOG.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,26 @@ and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0
1010
`Unreleased`_
1111
=============
1212

13+
Changed
14+
-------
15+
- `build_and_test.yml` workflow_dispatch trigger added
16+
- Updated `typing_extensions` dependency platform flags
17+
- Simplified conditional imports from `typing` with alternatives from `typing_extensions`
18+
that resolves it under the hood, so we need no control it manually
19+
- Legacy `collections.abc` imports replaced with `typing_extensions`
20+
cause current required `typing_extensions>=4.7` version already supports all them
21+
- Removed redundant (legacy) imports from `__future__`
22+
- Undefined annotations fixed
23+
24+
Added
25+
-----
26+
- Added `_compat.py` module to simplify future support for other python implementations, like `pypy` or `circuitpython`
27+
28+
Added
29+
-----
30+
- Added support for Pythonista iOS app backend.
31+
- Added ``BleakClient.name`` property for getting the peripheral's name. Fixes #1802.
32+
1333
Fixed
1434
-----
1535
- Fixed ``AttributeError`` in Python4Android backend when accessing ``is_connected`` before connecting. Fixes #1791.

bleak/__init__.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
"""Top-level package for bleak."""
44

5-
from __future__ import annotations
6-
75
__author__ = """Henrik Blidh"""
86
__email__ = "[email protected]"
97

@@ -14,22 +12,24 @@
1412
import os
1513
import sys
1614
import uuid
17-
from collections.abc import AsyncGenerator, Awaitable, Callable, Iterable
1815
from types import TracebackType
19-
from typing import Any, Literal, Optional, TypedDict, Union, cast, overload
20-
21-
if sys.version_info < (3, 12):
22-
from typing_extensions import Buffer
23-
else:
24-
from collections.abc import Buffer
16+
from typing import (
17+
Any,
18+
AsyncGenerator,
19+
Awaitable,
20+
Callable,
21+
Iterable,
22+
Literal,
23+
Optional,
24+
TypedDict,
25+
Union,
26+
cast,
27+
overload,
28+
)
2529

26-
if sys.version_info < (3, 11):
27-
from async_timeout import timeout as async_timeout
28-
from typing_extensions import Never, Self, Unpack, assert_never
29-
else:
30-
from asyncio import timeout as async_timeout
31-
from typing import Never, Self, Unpack, assert_never
30+
from typing_extensions import Buffer, Never, Self, Unpack, assert_never
3231

32+
from bleak._compat import async_timeout
3333
from bleak.args.bluez import BlueZScannerArgs
3434
from bleak.args.corebluetooth import CBScannerArgs, CBStartNotifyArgs
3535
from bleak.args.winrt import WinRTClientArgs
@@ -481,7 +481,7 @@ class BleakClient:
481481
def __init__(
482482
self,
483483
address_or_ble_device: Union[BLEDevice, str],
484-
disconnected_callback: Optional[Callable[[BleakClient], None]] = None,
484+
disconnected_callback: Optional[Callable[["BleakClient"], None]] = None,
485485
services: Optional[Iterable[str]] = None,
486486
*,
487487
timeout: float = 10.0,

bleak/_compat.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import asyncio
2+
import sys
3+
4+
if sys.implementation.name == "cpython":
5+
if sys.version_info < (3, 11):
6+
from async_timeout import timeout as async_timeout
7+
else:
8+
from asyncio import timeout as async_timeout
9+
10+
elif sys.implementation.name == "circuitpython":
11+
# This code is preparing the bleak to be compatible with `circuitpython>=9`
12+
13+
if sys.implementation.version <= (9,):
14+
raise NotImplementedError("Bleak does not support CircuitPython < 9")
15+
else:
16+
17+
class _AsyncTimeout:
18+
def __init__(self, timeout):
19+
if sys.implementation.name != "circuitpython":
20+
print(
21+
"Warning: This timeout manager is for CircuitPython. "
22+
"Use the native `asyncio.timeout` on standard Python."
23+
)
24+
self.timeout = timeout
25+
self._task = None
26+
27+
async def __aenter__(self):
28+
self._task = asyncio.create_task(asyncio.sleep(self.timeout))
29+
return self
30+
31+
async def __aexit__(self, exc_type, exc_val, exc_tb):
32+
if self._task and not self._task.done():
33+
self._task.cancel()
34+
try:
35+
await self._task
36+
except asyncio.CancelledError:
37+
pass
38+
39+
if exc_type is asyncio.CancelledError and self._task.done():
40+
if self._task.cancelled():
41+
raise asyncio.TimeoutError("Operation timed out") from exc_val
42+
43+
# If any other exception occurred, let it propagate.
44+
return False
45+
46+
async_timeout = _AsyncTimeout
47+
48+
elif sys.implementation.name == "pypy":
49+
raise NotImplementedError("Unsupported Python implementation: pypy")
50+
51+
else:
52+
# can't use on pypy for example
53+
raise NotImplementedError(
54+
f"Unsupported Python implementation: {sys.implementation.name}"
55+
)
56+
57+
assert async_timeout # Ensure we have async_timeout defined

bleak/args/corebluetooth.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
-------------------------------
55
"""
66

7-
from collections.abc import Callable
8-
from typing import Optional, TypedDict
7+
from typing import Callable, Optional, TypedDict
98

109

1110
class CBScannerArgs(TypedDict, total=False):

bleak/backends/bluezdbus/advertisement_monitor.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
assert False, "This backend is only available on Linux"
1515

1616
import logging
17-
from collections.abc import Iterable
18-
from typing import Any, no_type_check
17+
from typing import Any, Iterable, no_type_check
1918
from warnings import warn
2019

2120
from dbus_fast import PropertyAccess

bleak/backends/bluezdbus/client.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,10 @@
1313
import logging
1414
import os
1515
import warnings
16-
from collections.abc import Callable
1716
from contextlib import AsyncExitStack
18-
from typing import Any, Optional, Union
17+
from typing import Any, Callable, Optional, Union
1918

20-
if sys.version_info < (3, 12):
21-
from typing_extensions import Buffer, override
22-
else:
23-
from collections.abc import Buffer
24-
from typing import override
19+
from typing_extensions import Buffer, override
2520

2621
if sys.version_info < (3, 11):
2722
from async_timeout import timeout as async_timeout

bleak/backends/bluezdbus/manager.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
import logging
1919
import os
2020
from collections import defaultdict
21-
from collections.abc import Callable, Coroutine, MutableMapping
22-
from typing import Any, NamedTuple, Optional, cast
21+
from typing import Any, Callable, Coroutine, MutableMapping, NamedTuple, Optional, cast
2322
from weakref import WeakKeyDictionary
2423

2524
from dbus_fast import BusType, Message, MessageType, Variant, unpack_variants

bleak/backends/bluezdbus/scanner.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,11 @@
66
assert False, "This backend is only available on Linux"
77

88
import logging
9-
from collections.abc import Callable, Coroutine
10-
from typing import Any, Literal, Optional
9+
from typing import Any, Callable, Coroutine, Literal, Optional
1110
from warnings import warn
1211

13-
if sys.version_info < (3, 12):
14-
from typing_extensions import override
15-
else:
16-
from typing import override
17-
1812
from dbus_fast import Variant
13+
from typing_extensions import override
1914

2015
from bleak.args.bluez import BlueZDiscoveryFilters as _BlueZDiscoveryFilters
2116
from bleak.args.bluez import BlueZScannerArgs as _BlueZScannerArgs

bleak/backends/bluezdbus/signals.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
# -*- coding: utf-8 -*-
2-
from __future__ import annotations
3-
42
import sys
53
from typing import TYPE_CHECKING
64

@@ -144,7 +142,7 @@ def __init__(
144142
self.args = None
145143

146144
@staticmethod
147-
def parse(rules: str) -> MatchRules:
145+
def parse(rules: str) -> "MatchRules":
148146
return MatchRules(**dict(r.split("=") for r in rules.split(",")))
149147

150148
def __str__(self) -> str:

0 commit comments

Comments
 (0)