Skip to content

Commit 17e0a08

Browse files
authored
Merge branch 'pybricks:master' into master
2 parents 92b0d22 + 149b24a commit 17e0a08

File tree

14 files changed

+97
-93
lines changed

14 files changed

+97
-93
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ operations from within a Python script.
1616

1717
`pybricksdev` requires Python 3.10 or higher.
1818

19-
- For Windows, use the [official Python installer][py-dl] or the [Windows Store][py38-win].
19+
- For Windows, use the [official Python installer][py-dl] or the [Windows Store][py312-win].
2020
- For Mac, use the [official Python installer][py-dl] or Homebrew (`brew install [email protected]`).
2121
- For Linux, use the distro provided `python3.12` or if not available, use a Python
2222
runtime version manager such as [asdf][asdf] or [pyenv][pyenv].
2323

2424

2525
[py-dl]: https://www.python.org/downloads/
26-
[py38-win]: https://www.microsoft.com/en-us/p/python-38/9mssztt1n39l
26+
[py312-win]: https://apps.microsoft.com/detail/9ncvdn91xzqp
2727
[asdf]: https://asdf-vm.com
2828
[pyenv]: https://github.com/pyenv/pyenv
2929

docs/conf.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@
6565
("py:class", "bleak.backends.device.BLEDevice"),
6666
("py:exc", "asyncio.TimeoutError"),
6767
("py:class", "bleak.BleakClient"),
68-
("py:obj", "typing.Union"),
6968
("py:class", "os.PathLike"),
7069
("py:obj", "typing.BinaryIO"),
7170
("py:class", "BinaryIO"), # yes, we need both!

pybricksdev/ble/__init__.py

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

44
import asyncio
55
import logging
6-
from typing import Optional
76

87
from bleak import BleakClient, BleakScanner
98
from bleak.backends.device import BLEDevice
@@ -16,7 +15,7 @@
1615

1716

1817
async def find_device(
19-
name: Optional[str] = None,
18+
name: str | None = None,
2019
service: str = PYBRICKS_SERVICE_UUID,
2120
timeout: float = 10,
2221
) -> BLEDevice:

pybricksdev/ble/lwp3/bytecodes.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@
1111
"""
1212

1313
from enum import IntEnum, IntFlag, unique
14-
from typing import Type, Union
1514

1615

17-
def _create_pseudo_member_(cls: Type[IntEnum], value: int) -> IntEnum:
16+
def _create_pseudo_member_(cls: type[IntEnum], value: int) -> IntEnum:
1817
"""
1918
Creates a new enum member at runtime for ``IntEnum``s.
2019
"""
@@ -122,7 +121,7 @@ class BluetoothAddress(bytes):
122121
identifying individual Bluetooth devices instead of network cards.
123122
"""
124123

125-
def __new__(cls, value: Union[str, bytes]) -> "BluetoothAddress":
124+
def __new__(cls, value: str | bytes) -> "BluetoothAddress":
126125
if isinstance(value, str):
127126
# if it is a string, assume the format "XX:XX:XX:XX:XX:XX"
128127
value = [int(x, 16) for x in value.split(":")]

pybricksdev/ble/lwp3/messages.py

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import abc
1414
import struct
1515
from enum import IntEnum
16-
from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Type, Union, overload
16+
from typing import Any, NamedTuple, overload
1717

1818
from pybricksdev.ble.lwp3.bytecodes import (
1919
MAX_NAME_SIZE,
@@ -144,7 +144,7 @@ def __repr__(self) -> str:
144144
class _HubPropertyType(NamedTuple):
145145
type: type
146146
fmt: str
147-
max_size: Optional[int] = None
147+
max_size: int | None = None
148148

149149

150150
# specifies payload type information for each property
@@ -861,7 +861,7 @@ def __repr__(self) -> str:
861861

862862

863863
class PortFormatSetupComboMessage(AbstractPortFormatSetupComboMessage):
864-
def __init__(self, port: PortID, modes_and_datasets: List[Tuple[int, int]]) -> None:
864+
def __init__(self, port: PortID, modes_and_datasets: list[tuple[int, int]]) -> None:
865865
super().__init__(
866866
5 + len(modes_and_datasets), port, PortInfoFormatSetupCommand.SET
867867
)
@@ -870,7 +870,7 @@ def __init__(self, port: PortID, modes_and_datasets: List[Tuple[int, int]]) -> N
870870
self._data[i] = ((mode & 0xF) << 4) | (dataset & 0xF)
871871

872872
@property
873-
def modes_and_datasets(self) -> List[Tuple[int, int]]:
873+
def modes_and_datasets(self) -> list[tuple[int, int]]:
874874
return [(x >> 4, x & 0xF) for x in self._data[5:]]
875875

876876
def __repr__(self) -> str:
@@ -923,8 +923,8 @@ def __init__(
923923
port: PortID,
924924
capabilities: ModeCapabilities,
925925
num_modes: int,
926-
input_modes: List[int],
927-
output_modes: List[int],
926+
input_modes: list[int],
927+
output_modes: list[int],
928928
) -> None:
929929
super().__init__(11, port, InfoKind.MODE_INFO)
930930

@@ -955,12 +955,12 @@ def num_modes(self) -> int:
955955
return self._data[6]
956956

957957
@property
958-
def input_modes(self) -> List[int]:
958+
def input_modes(self) -> list[int]:
959959
(flags,) = struct.unpack_from("<H", self._data, 7)
960960
return [n for n in range(16) if flags & (1 << n)]
961961

962962
@property
963-
def output_modes(self) -> List[int]:
963+
def output_modes(self) -> list[int]:
964964
(flags,) = struct.unpack_from("<H", self._data, 9)
965965
return [n for n in range(16) if flags & (1 << n)]
966966

@@ -972,7 +972,7 @@ class PortInfoCombosMessage(AbstractPortInfoMessage):
972972
def __init__(
973973
self,
974974
port: PortID,
975-
combos: List[List[int]],
975+
combos: list[list[int]],
976976
) -> None:
977977
super().__init__(5 + len(combos) * 2, port, InfoKind.COMBOS)
978978

@@ -988,7 +988,7 @@ def __init__(
988988
struct.pack_into(f"<{len(flags)}H", self._data, 5, *flags)
989989

990990
@property
991-
def combos(self) -> List[List[int]]:
991+
def combos(self) -> list[list[int]]:
992992
count = (len(self._data) - 5) // 2
993993
return [
994994
[m for m in range(16) if flags & (1 << m)]
@@ -1211,7 +1211,7 @@ def __repr__(self) -> str:
12111211

12121212

12131213
class PortValueMessage(AbstractMessage):
1214-
def __init__(self, port: PortID, fmt: str, *values: Union[int, float]) -> None:
1214+
def __init__(self, port: PortID, fmt: str, *values: int | float) -> None:
12151215
super().__init__(4 + struct.calcsize(fmt), MessageKind.PORT_VALUE)
12161216

12171217
self._data[3] = port
@@ -1221,7 +1221,7 @@ def __init__(self, port: PortID, fmt: str, *values: Union[int, float]) -> None:
12211221
def port(self) -> PortID:
12221222
return PortID(self._data[3])
12231223

1224-
def unpack(self, fmt: str) -> Tuple[Union[int, float], ...]:
1224+
def unpack(self, fmt: str) -> tuple[int | float, ...]:
12251225
return struct.unpack_from(fmt, self._data, 4)
12261226

12271227
def __repr__(self) -> str:
@@ -1232,7 +1232,7 @@ def __repr__(self) -> str:
12321232

12331233
class PortValueComboMessage(AbstractMessage):
12341234
def __init__(
1235-
self, port: PortID, modes: List[int], fmt: str, *values: Union[int, float]
1235+
self, port: PortID, modes: list[int], fmt: str, *values: int | float
12361236
) -> None:
12371237
super().__init__(6 + struct.calcsize(fmt), MessageKind.PORT_VALUE_COMBO)
12381238

@@ -1249,11 +1249,11 @@ def port(self) -> PortID:
12491249
return PortID(self._data[3])
12501250

12511251
@property
1252-
def modes(self) -> List[int]:
1252+
def modes(self) -> list[int]:
12531253
(flags,) = struct.unpack_from("<H", self._data, 4)
12541254
return [m for m in range(16) if flags & (1 << m)]
12551255

1256-
def unpack(self, fmt: str) -> Tuple[Union[int, float], ...]:
1256+
def unpack(self, fmt: str) -> tuple[int | float, ...]:
12571257
return struct.unpack_from(fmt, self._data, 6)
12581258

12591259
def __repr__(self) -> str:
@@ -1294,7 +1294,7 @@ def __init__(
12941294
port: PortID,
12951295
combo: int,
12961296
multi_update: bool,
1297-
modes_and_datasets: List[int],
1297+
modes_and_datasets: list[int],
12981298
) -> None:
12991299
super().__init__(7, MessageKind.PORT_INPUT_FMT_COMBO)
13001300

@@ -1321,7 +1321,7 @@ def multi_update(self) -> bool:
13211321
return bool(self._data[4] & 0x80)
13221322

13231323
@property
1324-
def modes_and_datasets(self) -> List[int]:
1324+
def modes_and_datasets(self) -> list[int]:
13251325
(flags,) = struct.unpack_from("<H", self._data, 5)
13261326
return [m for m in range(16) if flags & (1 << m)]
13271327

@@ -1450,7 +1450,7 @@ def __init__(
14501450
end: EndInfo,
14511451
mode: int,
14521452
fmt: str,
1453-
*values: Union[int, float],
1453+
*values: int | float,
14541454
) -> None:
14551455
super().__init__(
14561456
7 + struct.calcsize(fmt),
@@ -1467,7 +1467,7 @@ def __init__(
14671467
def mode(self) -> int:
14681468
return self._data[6]
14691469

1470-
def unpack(self, fmt: str) -> Tuple[Union[int, float], ...]:
1470+
def unpack(self, fmt: str) -> tuple[int | float, ...]:
14711471
return struct.unpack_from(fmt, self._data, 7)
14721472

14731473
def __repr__(self) -> str:
@@ -1500,10 +1500,10 @@ def __init__(
15001500
self,
15011501
port1: PortID,
15021502
feedback1: Feedback,
1503-
port2: Optional[PortID] = None,
1504-
feedback2: Optional[Feedback] = None,
1505-
port3: Optional[PortID] = None,
1506-
feedback3: Optional[Feedback] = None,
1503+
port2: PortID | None = None,
1504+
feedback2: Feedback | None = None,
1505+
port3: PortID | None = None,
1506+
feedback3: Feedback | None = None,
15071507
) -> None:
15081508
length = 5
15091509

@@ -1577,7 +1577,7 @@ class _Lookup(NamedTuple):
15771577
index: int
15781578
"""The index of the bytecode that determines the type."""
15791579

1580-
value: Union[Dict[IntEnum, Type[AbstractMessage]], Dict[IntEnum, "_Lookup"]]
1580+
value: dict[IntEnum, type[AbstractMessage]] | dict[IntEnum, "_Lookup"]
15811581
"""
15821582
A dictionary mapping a bytecode to the cooresponding Python type if the type can be determined or
15831583
a dictionary mapping a bytecode to another lookup if more discrimination is required.

pybricksdev/ble/pybricks.py

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

2222
from enum import IntEnum, IntFlag
2323
from struct import unpack
24-
from typing import Literal, Tuple
24+
from typing import Literal
2525

2626
import semver
2727

@@ -351,7 +351,7 @@ class UserProgramId(IntEnum):
351351
"""
352352

353353

354-
def unpack_hub_capabilities(data: bytes) -> Tuple[int, HubCapabilityFlag, int, int]:
354+
def unpack_hub_capabilities(data: bytes) -> tuple[int, HubCapabilityFlag, int, int]:
355355
"""
356356
Unpacks the value read from the hub capabilities characteristic.
357357
@@ -373,7 +373,7 @@ def unpack_hub_capabilities(data: bytes) -> Tuple[int, HubCapabilityFlag, int, i
373373
return max_char_size, HubCapabilityFlag(flags), max_user_prog_size, num_of_slots
374374

375375

376-
def unpack_hub_capabilities_v15(data: bytes) -> Tuple[int, HubCapabilityFlag, int, int]:
376+
def unpack_hub_capabilities_v15(data: bytes) -> tuple[int, HubCapabilityFlag, int, int]:
377377
"""
378378
Unpacks the value read from the hub capabilities characteristic. (Pybricks protocol v1.5)
379379
@@ -459,7 +459,7 @@ def short_uuid(uuid: str) -> int:
459459
"""
460460

461461

462-
def unpack_pnp_id(data: bytes) -> Tuple[Literal["BT", "USB"], int, int, int]:
462+
def unpack_pnp_id(data: bytes) -> tuple[Literal["BT", "USB"], int, int, int]:
463463
"""
464464
Unpacks raw data from the PnP ID characteristic.
465465

pybricksdev/cli/flash.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import sys
99
import zlib
1010
from tempfile import NamedTemporaryFile
11-
from typing import BinaryIO, Dict, Optional
11+
from typing import BinaryIO
1212

1313
from bleak import BleakClient, BleakScanner
1414
from bleak.backends.device import BLEDevice
@@ -273,7 +273,7 @@ async def flash_ble(hub_kind: HubKind, firmware: bytes, metadata: dict):
273273
# as return value from find_device_by_filter()
274274
# https://github.com/hbldh/bleak/issues/1277
275275

276-
device_adv_map: Dict[str, AdvertisementData] = {}
276+
device_adv_map: dict[str, AdvertisementData] = {}
277277

278278
def map_and_match(device: BLEDevice, adv: AdvertisementData):
279279
# capture the adv data for later use
@@ -391,17 +391,19 @@ async def tick(callback):
391391
callback(CHUNK)
392392

393393
print("Erasing memory and preparing firmware download...")
394-
with logging_redirect_tqdm(), tqdm(
395-
total=len(firmware), unit="B", unit_scale=True
396-
) as pbar:
394+
with (
395+
logging_redirect_tqdm(),
396+
tqdm(total=len(firmware), unit="B", unit_scale=True) as pbar,
397+
):
397398
await asyncio.gather(
398399
bootloader.erase_and_begin_download(len(firmware)), tick(pbar.update)
399400
)
400401

401402
print("Downloading firmware...")
402-
with logging_redirect_tqdm(), tqdm(
403-
total=len(firmware), unit="B", unit_scale=True
404-
) as pbar:
403+
with (
404+
logging_redirect_tqdm(),
405+
tqdm(total=len(firmware), unit="B", unit_scale=True) as pbar,
406+
):
405407
await bootloader.download(firmware, pbar.update)
406408

407409
print("Verifying...", end="", flush=True)
@@ -419,7 +421,7 @@ async def tick(callback):
419421
print("Done.")
420422

421423

422-
async def flash_firmware(firmware_zip: BinaryIO, new_name: Optional[str]) -> None:
424+
async def flash_firmware(firmware_zip: BinaryIO, new_name: str | None) -> None:
423425
"""
424426
Command line tool for flashing firmware.
425427

pybricksdev/cli/oad.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,12 @@ def on_disconnect(_):
7373
disconnect_event.set()
7474

7575
# long timeout in case pairing is needed
76-
async with asyncio.timeout(60), BleakClient(
77-
device, on_disconnect
78-
) as client, OADImageIdentify(client) as image_identify, OADControlPoint(
79-
client
80-
) as control_point:
76+
async with (
77+
asyncio.timeout(60),
78+
BleakClient(device, on_disconnect) as client,
79+
OADImageIdentify(client) as image_identify,
80+
OADControlPoint(client) as control_point,
81+
):
8182
image_block = OADImageBlock(client)
8283

8384
print(f"Connected to {device.name}")
@@ -107,9 +108,10 @@ def on_disconnect(_):
107108

108109
print("Flashing...")
109110

110-
with logging_redirect_tqdm(), tqdm(
111-
total=header.image_length, unit="B", unit_scale=True
112-
) as pbar:
111+
with (
112+
logging_redirect_tqdm(),
113+
tqdm(total=header.image_length, unit="B", unit_scale=True) as pbar,
114+
):
113115
async with asyncio.TaskGroup() as group:
114116
try:
115117
async for (
@@ -161,9 +163,11 @@ async def dump_oad_info():
161163
return
162164

163165
# long timeout in case pairing is needed
164-
async with asyncio.timeout(30), BleakClient(device) as client, OADControlPoint(
165-
client
166-
) as control_point:
166+
async with (
167+
asyncio.timeout(30),
168+
BleakClient(device) as client,
169+
OADControlPoint(client) as control_point,
170+
):
167171
sw_ver = await control_point.get_software_version()
168172
print(
169173
f"Software version: app={sw_ver.app.major}.{sw_ver.app.minor}, stack={sw_ver.stack.major}.{sw_ver.stack.minor}"

0 commit comments

Comments
 (0)