bumble 0.0.212__py3-none-any.whl → 0.0.214__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. bumble/_version.py +2 -2
  2. bumble/a2dp.py +6 -0
  3. bumble/apps/README.md +0 -3
  4. bumble/apps/auracast.py +14 -11
  5. bumble/apps/bench.py +482 -37
  6. bumble/apps/console.py +3 -3
  7. bumble/apps/controller_info.py +44 -12
  8. bumble/apps/controller_loopback.py +7 -7
  9. bumble/apps/controllers.py +4 -5
  10. bumble/apps/device_info.py +4 -5
  11. bumble/apps/gatt_dump.py +5 -5
  12. bumble/apps/gg_bridge.py +5 -5
  13. bumble/apps/hci_bridge.py +5 -4
  14. bumble/apps/l2cap_bridge.py +5 -5
  15. bumble/apps/lea_unicast/app.py +8 -3
  16. bumble/apps/pair.py +19 -11
  17. bumble/apps/pandora_server.py +2 -2
  18. bumble/apps/player/player.py +2 -3
  19. bumble/apps/rfcomm_bridge.py +3 -4
  20. bumble/apps/scan.py +4 -5
  21. bumble/apps/show.py +6 -4
  22. bumble/apps/speaker/speaker.html +1 -0
  23. bumble/apps/speaker/speaker.js +113 -62
  24. bumble/apps/speaker/speaker.py +123 -19
  25. bumble/apps/unbond.py +2 -3
  26. bumble/apps/usb_probe.py +2 -3
  27. bumble/at.py +4 -4
  28. bumble/att.py +2 -6
  29. bumble/avc.py +7 -7
  30. bumble/avctp.py +3 -3
  31. bumble/avdtp.py +16 -20
  32. bumble/avrcp.py +42 -54
  33. bumble/colors.py +2 -2
  34. bumble/controller.py +174 -45
  35. bumble/device.py +398 -182
  36. bumble/drivers/__init__.py +2 -2
  37. bumble/drivers/common.py +0 -2
  38. bumble/drivers/intel.py +37 -40
  39. bumble/drivers/rtk.py +28 -35
  40. bumble/gatt.py +4 -4
  41. bumble/gatt_adapters.py +4 -5
  42. bumble/gatt_client.py +26 -31
  43. bumble/gatt_server.py +7 -11
  44. bumble/hci.py +2648 -2909
  45. bumble/helpers.py +4 -5
  46. bumble/hfp.py +32 -37
  47. bumble/host.py +104 -35
  48. bumble/keys.py +5 -5
  49. bumble/l2cap.py +312 -409
  50. bumble/link.py +16 -280
  51. bumble/logging.py +65 -0
  52. bumble/pairing.py +23 -20
  53. bumble/pandora/__init__.py +2 -2
  54. bumble/pandora/config.py +2 -2
  55. bumble/pandora/device.py +6 -6
  56. bumble/pandora/host.py +27 -28
  57. bumble/pandora/l2cap.py +2 -2
  58. bumble/pandora/security.py +6 -6
  59. bumble/pandora/utils.py +3 -3
  60. bumble/profiles/ams.py +404 -0
  61. bumble/profiles/ascs.py +142 -131
  62. bumble/profiles/asha.py +2 -2
  63. bumble/profiles/bap.py +3 -4
  64. bumble/profiles/csip.py +2 -2
  65. bumble/profiles/device_information_service.py +2 -2
  66. bumble/profiles/gap.py +2 -2
  67. bumble/profiles/hap.py +34 -33
  68. bumble/profiles/le_audio.py +4 -4
  69. bumble/profiles/mcp.py +4 -4
  70. bumble/profiles/vcs.py +3 -5
  71. bumble/rfcomm.py +10 -10
  72. bumble/rtp.py +1 -2
  73. bumble/sdp.py +2 -2
  74. bumble/smp.py +62 -63
  75. bumble/tools/intel_util.py +3 -2
  76. bumble/tools/rtk_util.py +6 -5
  77. bumble/transport/__init__.py +2 -16
  78. bumble/transport/android_netsim.py +5 -5
  79. bumble/transport/common.py +4 -4
  80. bumble/transport/pyusb.py +2 -2
  81. bumble/utils.py +2 -5
  82. bumble/vendor/android/hci.py +118 -200
  83. bumble/vendor/zephyr/hci.py +32 -27
  84. {bumble-0.0.212.dist-info → bumble-0.0.214.dist-info}/METADATA +4 -3
  85. {bumble-0.0.212.dist-info → bumble-0.0.214.dist-info}/RECORD +89 -90
  86. {bumble-0.0.212.dist-info → bumble-0.0.214.dist-info}/WHEEL +1 -1
  87. {bumble-0.0.212.dist-info → bumble-0.0.214.dist-info}/entry_points.txt +0 -1
  88. bumble/apps/link_relay/__init__.py +0 -0
  89. bumble/apps/link_relay/link_relay.py +0 -289
  90. bumble/apps/link_relay/logging.yml +0 -21
  91. {bumble-0.0.212.dist-info → bumble-0.0.214.dist-info}/licenses/LICENSE +0 -0
  92. {bumble-0.0.212.dist-info → bumble-0.0.214.dist-info}/top_level.txt +0 -0
bumble/avctp.py CHANGED
@@ -19,7 +19,7 @@ from __future__ import annotations
19
19
  from enum import IntEnum
20
20
  import logging
21
21
  import struct
22
- from typing import Callable, cast, Dict, Optional
22
+ from typing import Callable, cast, Optional
23
23
 
24
24
  from bumble.colors import color
25
25
  from bumble import avc
@@ -146,9 +146,9 @@ class MessageAssembler:
146
146
  # -----------------------------------------------------------------------------
147
147
  class Protocol:
148
148
  CommandHandler = Callable[[int, avc.CommandFrame], None]
149
- command_handlers: Dict[int, CommandHandler] # Command handlers, by PID
149
+ command_handlers: dict[int, CommandHandler] # Command handlers, by PID
150
150
  ResponseHandler = Callable[[int, Optional[avc.ResponseFrame]], None]
151
- response_handlers: Dict[int, ResponseHandler] # Response handlers, by PID
151
+ response_handlers: dict[int, ResponseHandler] # Response handlers, by PID
152
152
  next_transaction_label: int
153
153
  message_assembler: MessageAssembler
154
154
 
bumble/avdtp.py CHANGED
@@ -24,12 +24,8 @@ import warnings
24
24
  from typing import (
25
25
  Any,
26
26
  Awaitable,
27
- Dict,
28
- Type,
29
- Tuple,
30
27
  Optional,
31
28
  Callable,
32
- List,
33
29
  AsyncGenerator,
34
30
  Iterable,
35
31
  Union,
@@ -227,7 +223,7 @@ AVDTP_STATE_NAMES = {
227
223
  # -----------------------------------------------------------------------------
228
224
  async def find_avdtp_service_with_sdp_client(
229
225
  sdp_client: sdp.Client,
230
- ) -> Optional[Tuple[int, int]]:
226
+ ) -> Optional[tuple[int, int]]:
231
227
  '''
232
228
  Find an AVDTP service, using a connected SDP client, and return its version,
233
229
  or None if none is found
@@ -257,7 +253,7 @@ async def find_avdtp_service_with_sdp_client(
257
253
  # -----------------------------------------------------------------------------
258
254
  async def find_avdtp_service_with_connection(
259
255
  connection: device.Connection,
260
- ) -> Optional[Tuple[int, int]]:
256
+ ) -> Optional[tuple[int, int]]:
261
257
  '''
262
258
  Find an AVDTP service, for a connection, and return its version,
263
259
  or None if none is found
@@ -451,7 +447,7 @@ class ServiceCapabilities:
451
447
  service_category: int, service_capabilities_bytes: bytes
452
448
  ) -> ServiceCapabilities:
453
449
  # Select the appropriate subclass
454
- cls: Type[ServiceCapabilities]
450
+ cls: type[ServiceCapabilities]
455
451
  if service_category == AVDTP_MEDIA_CODEC_SERVICE_CATEGORY:
456
452
  cls = MediaCodecCapabilities
457
453
  else:
@@ -466,7 +462,7 @@ class ServiceCapabilities:
466
462
  return instance
467
463
 
468
464
  @staticmethod
469
- def parse_capabilities(payload: bytes) -> List[ServiceCapabilities]:
465
+ def parse_capabilities(payload: bytes) -> list[ServiceCapabilities]:
470
466
  capabilities = []
471
467
  while payload:
472
468
  service_category = payload[0]
@@ -499,7 +495,7 @@ class ServiceCapabilities:
499
495
  self.service_category = service_category
500
496
  self.service_capabilities_bytes = service_capabilities_bytes
501
497
 
502
- def to_string(self, details: Optional[List[str]] = None) -> str:
498
+ def to_string(self, details: Optional[list[str]] = None) -> str:
503
499
  attributes = ','.join(
504
500
  [name_or_number(AVDTP_SERVICE_CATEGORY_NAMES, self.service_category)]
505
501
  + (details or [])
@@ -612,7 +608,7 @@ class Message: # pylint:disable=attribute-defined-outside-init
612
608
  RESPONSE_REJECT = 3
613
609
 
614
610
  # Subclasses, by signal identifier and message type
615
- subclasses: Dict[int, Dict[int, Type[Message]]] = {}
611
+ subclasses: dict[int, dict[int, type[Message]]] = {}
616
612
  message_type: MessageType
617
613
  signal_identifier: int
618
614
 
@@ -757,7 +753,7 @@ class Discover_Response(Message):
757
753
  See Bluetooth AVDTP spec - 8.6.2 Stream End Point Discovery Response
758
754
  '''
759
755
 
760
- endpoints: List[EndPointInfo]
756
+ endpoints: list[EndPointInfo]
761
757
 
762
758
  def init_from_payload(self):
763
759
  self.endpoints = []
@@ -1202,10 +1198,10 @@ class DelayReport_Reject(Simple_Reject):
1202
1198
 
1203
1199
  # -----------------------------------------------------------------------------
1204
1200
  class Protocol(utils.EventEmitter):
1205
- local_endpoints: List[LocalStreamEndPoint]
1206
- remote_endpoints: Dict[int, DiscoveredStreamEndPoint]
1207
- streams: Dict[int, Stream]
1208
- transaction_results: List[Optional[asyncio.Future[Message]]]
1201
+ local_endpoints: list[LocalStreamEndPoint]
1202
+ remote_endpoints: dict[int, DiscoveredStreamEndPoint]
1203
+ streams: dict[int, Stream]
1204
+ transaction_results: list[Optional[asyncio.Future[Message]]]
1209
1205
  channel_connector: Callable[[], Awaitable[l2cap.ClassicChannel]]
1210
1206
 
1211
1207
  EVENT_OPEN = "open"
@@ -1223,7 +1219,7 @@ class Protocol(utils.EventEmitter):
1223
1219
 
1224
1220
  @staticmethod
1225
1221
  async def connect(
1226
- connection: device.Connection, version: Tuple[int, int] = (1, 3)
1222
+ connection: device.Connection, version: tuple[int, int] = (1, 3)
1227
1223
  ) -> Protocol:
1228
1224
  channel = await connection.create_l2cap_channel(
1229
1225
  spec=l2cap.ClassicChannelSpec(psm=AVDTP_PSM)
@@ -1233,7 +1229,7 @@ class Protocol(utils.EventEmitter):
1233
1229
  return protocol
1234
1230
 
1235
1231
  def __init__(
1236
- self, l2cap_channel: l2cap.ClassicChannel, version: Tuple[int, int] = (1, 3)
1232
+ self, l2cap_channel: l2cap.ClassicChannel, version: tuple[int, int] = (1, 3)
1237
1233
  ) -> None:
1238
1234
  super().__init__()
1239
1235
  self.l2cap_channel = l2cap_channel
@@ -1502,7 +1498,7 @@ class Protocol(utils.EventEmitter):
1502
1498
 
1503
1499
  return response
1504
1500
 
1505
- async def start_transaction(self) -> Tuple[int, asyncio.Future[Message]]:
1501
+ async def start_transaction(self) -> tuple[int, asyncio.Future[Message]]:
1506
1502
  # Wait until we can start a new transaction
1507
1503
  await self.transaction_semaphore.acquire()
1508
1504
 
@@ -1703,7 +1699,7 @@ class Protocol(utils.EventEmitter):
1703
1699
 
1704
1700
  # -----------------------------------------------------------------------------
1705
1701
  class Listener(utils.EventEmitter):
1706
- servers: Dict[int, Protocol]
1702
+ servers: dict[int, Protocol]
1707
1703
 
1708
1704
  EVENT_CONNECTION = "connection"
1709
1705
 
@@ -1735,7 +1731,7 @@ class Listener(utils.EventEmitter):
1735
1731
 
1736
1732
  @classmethod
1737
1733
  def for_device(
1738
- cls, device: device.Device, version: Tuple[int, int] = (1, 3)
1734
+ cls, device: device.Device, version: tuple[int, int] = (1, 3)
1739
1735
  ) -> Listener:
1740
1736
  listener = Listener(registrar=None, version=version)
1741
1737
  l2cap_server = device.create_l2cap_server(
bumble/avrcp.py CHANGED
@@ -26,14 +26,11 @@ from typing import (
26
26
  Awaitable,
27
27
  Callable,
28
28
  cast,
29
- Dict,
30
29
  Iterable,
31
30
  List,
32
31
  Optional,
33
32
  Sequence,
34
33
  SupportsBytes,
35
- Tuple,
36
- Type,
37
34
  TypeVar,
38
35
  Union,
39
36
  )
@@ -53,19 +50,10 @@ from bumble.sdp import (
53
50
  ServiceAttribute,
54
51
  )
55
52
  from bumble import utils
56
- from bumble.core import (
57
- InvalidArgumentError,
58
- ProtocolError,
59
- BT_L2CAP_PROTOCOL_ID,
60
- BT_AVCTP_PROTOCOL_ID,
61
- BT_AV_REMOTE_CONTROL_SERVICE,
62
- BT_AV_REMOTE_CONTROL_CONTROLLER_SERVICE,
63
- BT_AV_REMOTE_CONTROL_TARGET_SERVICE,
64
- )
53
+ from bumble import core
65
54
  from bumble import l2cap
66
55
  from bumble import avc
67
56
  from bumble import avctp
68
- from bumble import utils
69
57
 
70
58
 
71
59
  # -----------------------------------------------------------------------------
@@ -84,10 +72,10 @@ AVRCP_BLUETOOTH_SIG_COMPANY_ID = 0x001958
84
72
  # -----------------------------------------------------------------------------
85
73
  def make_controller_service_sdp_records(
86
74
  service_record_handle: int,
87
- avctp_version: Tuple[int, int] = (1, 4),
88
- avrcp_version: Tuple[int, int] = (1, 6),
75
+ avctp_version: tuple[int, int] = (1, 4),
76
+ avrcp_version: tuple[int, int] = (1, 6),
89
77
  supported_features: int = 1,
90
- ) -> List[ServiceAttribute]:
78
+ ) -> list[ServiceAttribute]:
91
79
  # TODO: support a way to compute the supported features from a feature list
92
80
  avctp_version_int = avctp_version[0] << 8 | avctp_version[1]
93
81
  avrcp_version_int = avrcp_version[0] << 8 | avrcp_version[1]
@@ -105,8 +93,8 @@ def make_controller_service_sdp_records(
105
93
  SDP_SERVICE_CLASS_ID_LIST_ATTRIBUTE_ID,
106
94
  DataElement.sequence(
107
95
  [
108
- DataElement.uuid(BT_AV_REMOTE_CONTROL_SERVICE),
109
- DataElement.uuid(BT_AV_REMOTE_CONTROL_CONTROLLER_SERVICE),
96
+ DataElement.uuid(core.BT_AV_REMOTE_CONTROL_SERVICE),
97
+ DataElement.uuid(core.BT_AV_REMOTE_CONTROL_CONTROLLER_SERVICE),
110
98
  ]
111
99
  ),
112
100
  ),
@@ -116,13 +104,13 @@ def make_controller_service_sdp_records(
116
104
  [
117
105
  DataElement.sequence(
118
106
  [
119
- DataElement.uuid(BT_L2CAP_PROTOCOL_ID),
107
+ DataElement.uuid(core.BT_L2CAP_PROTOCOL_ID),
120
108
  DataElement.unsigned_integer_16(avctp.AVCTP_PSM),
121
109
  ]
122
110
  ),
123
111
  DataElement.sequence(
124
112
  [
125
- DataElement.uuid(BT_AVCTP_PROTOCOL_ID),
113
+ DataElement.uuid(core.BT_AVCTP_PROTOCOL_ID),
126
114
  DataElement.unsigned_integer_16(avctp_version_int),
127
115
  ]
128
116
  ),
@@ -135,7 +123,7 @@ def make_controller_service_sdp_records(
135
123
  [
136
124
  DataElement.sequence(
137
125
  [
138
- DataElement.uuid(BT_AV_REMOTE_CONTROL_SERVICE),
126
+ DataElement.uuid(core.BT_AV_REMOTE_CONTROL_SERVICE),
139
127
  DataElement.unsigned_integer_16(avrcp_version_int),
140
128
  ]
141
129
  ),
@@ -152,10 +140,10 @@ def make_controller_service_sdp_records(
152
140
  # -----------------------------------------------------------------------------
153
141
  def make_target_service_sdp_records(
154
142
  service_record_handle: int,
155
- avctp_version: Tuple[int, int] = (1, 4),
156
- avrcp_version: Tuple[int, int] = (1, 6),
143
+ avctp_version: tuple[int, int] = (1, 4),
144
+ avrcp_version: tuple[int, int] = (1, 6),
157
145
  supported_features: int = 0x23,
158
- ) -> List[ServiceAttribute]:
146
+ ) -> list[ServiceAttribute]:
159
147
  # TODO: support a way to compute the supported features from a feature list
160
148
  avctp_version_int = avctp_version[0] << 8 | avctp_version[1]
161
149
  avrcp_version_int = avrcp_version[0] << 8 | avrcp_version[1]
@@ -173,7 +161,7 @@ def make_target_service_sdp_records(
173
161
  SDP_SERVICE_CLASS_ID_LIST_ATTRIBUTE_ID,
174
162
  DataElement.sequence(
175
163
  [
176
- DataElement.uuid(BT_AV_REMOTE_CONTROL_TARGET_SERVICE),
164
+ DataElement.uuid(core.BT_AV_REMOTE_CONTROL_TARGET_SERVICE),
177
165
  ]
178
166
  ),
179
167
  ),
@@ -183,13 +171,13 @@ def make_target_service_sdp_records(
183
171
  [
184
172
  DataElement.sequence(
185
173
  [
186
- DataElement.uuid(BT_L2CAP_PROTOCOL_ID),
174
+ DataElement.uuid(core.BT_L2CAP_PROTOCOL_ID),
187
175
  DataElement.unsigned_integer_16(avctp.AVCTP_PSM),
188
176
  ]
189
177
  ),
190
178
  DataElement.sequence(
191
179
  [
192
- DataElement.uuid(BT_AVCTP_PROTOCOL_ID),
180
+ DataElement.uuid(core.BT_AVCTP_PROTOCOL_ID),
193
181
  DataElement.unsigned_integer_16(avctp_version_int),
194
182
  ]
195
183
  ),
@@ -202,7 +190,7 @@ def make_target_service_sdp_records(
202
190
  [
203
191
  DataElement.sequence(
204
192
  [
205
- DataElement.uuid(BT_AV_REMOTE_CONTROL_SERVICE),
193
+ DataElement.uuid(core.BT_AV_REMOTE_CONTROL_SERVICE),
206
194
  DataElement.unsigned_integer_16(avrcp_version_int),
207
195
  ]
208
196
  ),
@@ -291,7 +279,7 @@ class Command:
291
279
  pdu_id: Protocol.PduId
292
280
  parameter: bytes
293
281
 
294
- def to_string(self, properties: Dict[str, str]) -> str:
282
+ def to_string(self, properties: dict[str, str]) -> str:
295
283
  properties_str = ",".join(
296
284
  [f"{name}={value}" for name, value in properties.items()]
297
285
  )
@@ -337,7 +325,7 @@ class GetPlayStatusCommand(Command):
337
325
  # -----------------------------------------------------------------------------
338
326
  class GetElementAttributesCommand(Command):
339
327
  identifier: int
340
- attribute_ids: List[MediaAttributeId]
328
+ attribute_ids: list[MediaAttributeId]
341
329
 
342
330
  @classmethod
343
331
  def from_bytes(cls, pdu: bytes) -> GetElementAttributesCommand:
@@ -409,7 +397,7 @@ class Response:
409
397
  pdu_id: Protocol.PduId
410
398
  parameter: bytes
411
399
 
412
- def to_string(self, properties: Dict[str, str]) -> str:
400
+ def to_string(self, properties: dict[str, str]) -> str:
413
401
  properties_str = ",".join(
414
402
  [f"{name}={value}" for name, value in properties.items()]
415
403
  )
@@ -454,7 +442,7 @@ class NotImplementedResponse(Response):
454
442
  # -----------------------------------------------------------------------------
455
443
  class GetCapabilitiesResponse(Response):
456
444
  capability_id: GetCapabilitiesCommand.CapabilityId
457
- capabilities: List[Union[SupportsBytes, bytes]]
445
+ capabilities: list[Union[SupportsBytes, bytes]]
458
446
 
459
447
  @classmethod
460
448
  def from_bytes(cls, pdu: bytes) -> GetCapabilitiesResponse:
@@ -467,7 +455,7 @@ class GetCapabilitiesResponse(Response):
467
455
  capability_id = GetCapabilitiesCommand.CapabilityId(pdu[0])
468
456
  capability_count = pdu[1]
469
457
 
470
- capabilities: List[Union[SupportsBytes, bytes]]
458
+ capabilities: list[Union[SupportsBytes, bytes]]
471
459
  if capability_id == GetCapabilitiesCommand.CapabilityId.EVENTS_SUPPORTED:
472
460
  capabilities = [EventId(pdu[2 + x]) for x in range(capability_count)]
473
461
  else:
@@ -540,13 +528,13 @@ class GetPlayStatusResponse(Response):
540
528
 
541
529
  # -----------------------------------------------------------------------------
542
530
  class GetElementAttributesResponse(Response):
543
- attributes: List[MediaAttribute]
531
+ attributes: list[MediaAttribute]
544
532
 
545
533
  @classmethod
546
534
  def from_bytes(cls, pdu: bytes) -> GetElementAttributesResponse:
547
535
  num_attributes = pdu[0]
548
536
  offset = 1
549
- attributes: List[MediaAttribute] = []
537
+ attributes: list[MediaAttribute] = []
550
538
  for _ in range(num_attributes):
551
539
  (
552
540
  attribute_id_int,
@@ -817,7 +805,7 @@ class PlayerApplicationSettingChangedEvent(Event):
817
805
  attribute_id: ApplicationSetting.AttributeId
818
806
  value_id: utils.OpenIntEnum
819
807
 
820
- player_application_settings: List[Setting]
808
+ player_application_settings: list[Setting]
821
809
 
822
810
  @classmethod
823
811
  def from_bytes(cls, pdu: bytes) -> PlayerApplicationSettingChangedEvent:
@@ -939,7 +927,7 @@ class VolumeChangedEvent(Event):
939
927
 
940
928
 
941
929
  # -----------------------------------------------------------------------------
942
- EVENT_SUBCLASSES: Dict[EventId, Type[Event]] = {
930
+ EVENT_SUBCLASSES: dict[EventId, type[Event]] = {
943
931
  EventId.PLAYBACK_STATUS_CHANGED: PlaybackStatusChangedEvent,
944
932
  EventId.PLAYBACK_POS_CHANGED: PlaybackPositionChangedEvent,
945
933
  EventId.TRACK_CHANGED: TrackChangedEvent,
@@ -967,14 +955,14 @@ class Delegate:
967
955
  def __init__(self, status_code: Protocol.StatusCode) -> None:
968
956
  self.status_code = status_code
969
957
 
970
- supported_events: List[EventId]
958
+ supported_events: list[EventId]
971
959
  volume: int
972
960
 
973
961
  def __init__(self, supported_events: Iterable[EventId] = ()) -> None:
974
962
  self.supported_events = list(supported_events)
975
963
  self.volume = 0
976
964
 
977
- async def get_supported_events(self) -> List[EventId]:
965
+ async def get_supported_events(self) -> list[EventId]:
978
966
  return self.supported_events
979
967
 
980
968
  async def set_absolute_volume(self, volume: int) -> None:
@@ -1124,12 +1112,12 @@ class Protocol(utils.EventEmitter):
1124
1112
  receive_response_state: Optional[ReceiveResponseState]
1125
1113
  avctp_protocol: Optional[avctp.Protocol]
1126
1114
  free_commands: asyncio.Queue
1127
- pending_commands: Dict[int, PendingCommand] # Pending commands, by label
1128
- notification_listeners: Dict[EventId, NotificationListener]
1115
+ pending_commands: dict[int, PendingCommand] # Pending commands, by label
1116
+ notification_listeners: dict[EventId, NotificationListener]
1129
1117
 
1130
1118
  @staticmethod
1131
1119
  def _check_vendor_dependent_frame(
1132
- frame: Union[avc.VendorDependentCommandFrame, avc.VendorDependentResponseFrame]
1120
+ frame: Union[avc.VendorDependentCommandFrame, avc.VendorDependentResponseFrame],
1133
1121
  ) -> bool:
1134
1122
  if frame.company_id != AVRCP_BLUETOOTH_SIG_COMPANY_ID:
1135
1123
  logger.debug("unsupported company id, ignoring")
@@ -1190,7 +1178,7 @@ class Protocol(utils.EventEmitter):
1190
1178
 
1191
1179
  @staticmethod
1192
1180
  def _check_response(
1193
- response_context: ResponseContext, expected_type: Type[_R]
1181
+ response_context: ResponseContext, expected_type: type[_R]
1194
1182
  ) -> _R:
1195
1183
  if isinstance(response_context, Protocol.FinalResponse):
1196
1184
  if (
@@ -1211,7 +1199,7 @@ class Protocol(utils.EventEmitter):
1211
1199
  def _delegate_command(
1212
1200
  self, transaction_label: int, command: Command, method: Awaitable
1213
1201
  ) -> None:
1214
- async def call():
1202
+ async def call() -> None:
1215
1203
  try:
1216
1204
  await method
1217
1205
  except Delegate.Error as error:
@@ -1230,7 +1218,7 @@ class Protocol(utils.EventEmitter):
1230
1218
 
1231
1219
  utils.AsyncRunner.spawn(call())
1232
1220
 
1233
- async def get_supported_events(self) -> List[EventId]:
1221
+ async def get_supported_events(self) -> list[EventId]:
1234
1222
  """Get the list of events supported by the connected peer."""
1235
1223
  response_context = await self.send_avrcp_command(
1236
1224
  avc.CommandFrame.CommandType.STATUS,
@@ -1253,7 +1241,7 @@ class Protocol(utils.EventEmitter):
1253
1241
 
1254
1242
  async def get_element_attributes(
1255
1243
  self, element_identifier: int, attribute_ids: Sequence[MediaAttributeId]
1256
- ) -> List[MediaAttribute]:
1244
+ ) -> list[MediaAttribute]:
1257
1245
  """Get element attributes from the connected peer."""
1258
1246
  response_context = await self.send_avrcp_command(
1259
1247
  avc.CommandFrame.CommandType.STATUS,
@@ -1335,7 +1323,7 @@ class Protocol(utils.EventEmitter):
1335
1323
 
1336
1324
  async def monitor_player_application_settings(
1337
1325
  self,
1338
- ) -> AsyncIterator[List[PlayerApplicationSettingChangedEvent.Setting]]:
1326
+ ) -> AsyncIterator[list[PlayerApplicationSettingChangedEvent.Setting]]:
1339
1327
  """Monitor Player Application Setting changes from the connected peer."""
1340
1328
  async for event in self.monitor_events(
1341
1329
  EventId.PLAYER_APPLICATION_SETTING_CHANGED, 0
@@ -1415,7 +1403,7 @@ class Protocol(utils.EventEmitter):
1415
1403
  def notify_track_changed(self, identifier: bytes) -> None:
1416
1404
  """Notify the connected peer of a Track change."""
1417
1405
  if len(identifier) != 8:
1418
- raise InvalidArgumentError("identifier must be 8 bytes")
1406
+ raise core.InvalidArgumentError("identifier must be 8 bytes")
1419
1407
  self.notify_event(TrackChangedEvent(identifier))
1420
1408
 
1421
1409
  def notify_playback_position_changed(self, position: int) -> None:
@@ -1682,7 +1670,7 @@ class Protocol(utils.EventEmitter):
1682
1670
  else:
1683
1671
  logger.debug("unexpected PDU ID")
1684
1672
  pending_command.response.set_exception(
1685
- ProtocolError(
1673
+ core.ProtocolError(
1686
1674
  error_code=None,
1687
1675
  error_namespace="avrcp",
1688
1676
  details="unexpected PDU ID",
@@ -1691,7 +1679,7 @@ class Protocol(utils.EventEmitter):
1691
1679
  else:
1692
1680
  logger.debug("unexpected response code")
1693
1681
  pending_command.response.set_exception(
1694
- ProtocolError(
1682
+ core.ProtocolError(
1695
1683
  error_code=None,
1696
1684
  error_namespace="avrcp",
1697
1685
  details="unexpected response code",
@@ -1869,12 +1857,12 @@ class Protocol(utils.EventEmitter):
1869
1857
  ) -> None:
1870
1858
  logger.debug(f"<<< AVRCP command PDU: {command}")
1871
1859
 
1872
- async def get_supported_events():
1860
+ async def get_supported_events() -> None:
1873
1861
  if (
1874
1862
  command.capability_id
1875
1863
  != GetCapabilitiesCommand.CapabilityId.EVENTS_SUPPORTED
1876
1864
  ):
1877
- raise Protocol.InvalidParameterError
1865
+ raise core.InvalidArgumentError()
1878
1866
 
1879
1867
  supported_events = await self.delegate.get_supported_events()
1880
1868
  self.send_avrcp_response(
@@ -1890,7 +1878,7 @@ class Protocol(utils.EventEmitter):
1890
1878
  ) -> None:
1891
1879
  logger.debug(f"<<< AVRCP command PDU: {command}")
1892
1880
 
1893
- async def set_absolute_volume():
1881
+ async def set_absolute_volume() -> None:
1894
1882
  await self.delegate.set_absolute_volume(command.volume)
1895
1883
  effective_volume = await self.delegate.get_absolute_volume()
1896
1884
  self.send_avrcp_response(
@@ -1906,7 +1894,7 @@ class Protocol(utils.EventEmitter):
1906
1894
  ) -> None:
1907
1895
  logger.debug(f"<<< AVRCP command PDU: {command}")
1908
1896
 
1909
- async def register_notification():
1897
+ async def register_notification() -> None:
1910
1898
  # Check if the event is supported.
1911
1899
  supported_events = await self.delegate.get_supported_events()
1912
1900
  if command.event_id not in supported_events:
bumble/colors.py CHANGED
@@ -13,7 +13,7 @@
13
13
  # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
14
 
15
15
  from functools import partial
16
- from typing import List, Optional, Union
16
+ from typing import Optional, Union
17
17
 
18
18
 
19
19
  class ColorError(ValueError):
@@ -65,7 +65,7 @@ def color(
65
65
  bg: Optional[ColorSpec] = None,
66
66
  style: Optional[str] = None,
67
67
  ) -> str:
68
- codes: List[ColorSpec] = []
68
+ codes: list[ColorSpec] = []
69
69
 
70
70
  if fg:
71
71
  codes.append(_color_code(fg, 30))