python-ember-mug 1.3.3__tar.gz → 1.4.0b2__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-ember-mug
3
- Version: 1.3.3
3
+ Version: 1.4.0b2
4
4
  Summary: Python Library for Ember Mugs.
5
5
  Project-URL: Changelog, https://sopelj.github.io/python-ember-mug/changelog/
6
6
  Project-URL: Documentation, https://sopelj.github.io/python-ember-mug/
@@ -18,8 +18,8 @@ Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Programming Language :: Python :: 3.13
19
19
  Classifier: Programming Language :: Python :: 3.14
20
20
  Requires-Python: >=3.11
21
- Requires-Dist: bleak-retry-connector>=4.0.2
22
- Requires-Dist: bleak<2.2.0,>=1.0.1
21
+ Requires-Dist: bleak-retry-connector>=4.6.0
22
+ Requires-Dist: bleak>=3.0.2
23
23
  Provides-Extra: dev
24
24
  Requires-Dist: ipython; extra == 'dev'
25
25
  Provides-Extra: docs
@@ -6,4 +6,4 @@ __all__ = ("EmberMug",)
6
6
 
7
7
  __author__ = """Jesse Sopel"""
8
8
  __email__ = "jesse@sopelj.ca"
9
- __version__ = "1.3.3"
9
+ __version__ = "1.4.0b2"
@@ -7,10 +7,11 @@ import contextlib
7
7
  import logging
8
8
  import re
9
9
  import sys
10
- from argparse import ArgumentParser, ArgumentTypeError, FileType, Namespace
11
- from typing import TYPE_CHECKING, ClassVar
10
+ from argparse import ArgumentParser, ArgumentTypeError, Namespace
11
+ from pathlib import Path
12
+ from typing import IO, TYPE_CHECKING, ClassVar
12
13
 
13
- from bleak import AdvertisementData, BleakError
14
+ from bleak import BleakError
14
15
 
15
16
  from ember_mug.consts import ATTR_LABELS, EMBER_BLE_SIG, EXTRA_ATTRS, IS_LINUX, TESTING_BLE_SIG, VolumeLevel
16
17
  from ember_mug.data import Colour, DeviceModel
@@ -25,6 +26,7 @@ from .helpers import CommandLoop, print_changes, print_info, print_table, valida
25
26
  if TYPE_CHECKING:
26
27
  from collections.abc import Awaitable, Callable
27
28
 
29
+ from bleak import AdvertisementData
28
30
  from bleak.backends.device import BLEDevice
29
31
 
30
32
  all_attrs = list(ATTR_LABELS) + list(EXTRA_ATTRS)
@@ -215,9 +217,8 @@ class EmberMugCli:
215
217
  )
216
218
  self.parser.add_argument(
217
219
  "--log-file",
218
- type=FileType("w", encoding="utf-8"),
220
+ type=Path,
219
221
  nargs="?",
220
- default=sys.stdout,
221
222
  help="File to write logs too (Will be overwritten)",
222
223
  )
223
224
  self.parser.add_argument("--version", action="version", version=__version__)
@@ -255,12 +256,23 @@ class EmberMugCli:
255
256
  async def run(self) -> None:
256
257
  """Run the specified command based on subparser."""
257
258
  args = self.parser.parse_args()
259
+ out_file: IO[str] | None = None
258
260
  if IS_LINUX is False:
259
261
  args.adapter = None # Set for other platforms
260
262
  if args.debug:
263
+ if args.log_file:
264
+ try:
265
+ out_file = args.log_file.open("w")
266
+ except OSError as e:
267
+ self.parser.error(f"Failed to open '{args.log_file}': {e}")
268
+
261
269
  logging.basicConfig(
262
- stream=args.log_file,
270
+ stream=out_file or sys.stdout,
263
271
  level=logging.DEBUG,
264
272
  format="[%(asctime)s] %(levelname)s [%(filename)s.%(funcName)s:%(lineno)d] %(message)s",
265
273
  )
266
- await self._commands[args.command](args)
274
+ try:
275
+ await self._commands[args.command](args)
276
+ finally:
277
+ if out_file is not None:
278
+ out_file.close()
@@ -206,7 +206,7 @@ class MugMeta(AsDict):
206
206
 
207
207
 
208
208
  @dataclass
209
- class MugData(AsDict):
209
+ class MugData:
210
210
  """Class to store/display the state of the mug."""
211
211
 
212
212
  # Options
@@ -266,11 +266,11 @@ class EmberMug:
266
266
 
267
267
  async def get_meta(self) -> MugMeta:
268
268
  """Fetch Meta info from the mug (Serial number and ID)."""
269
- return MugMeta.from_bytes(await self._read(MugCharacteristic.MUG_ID))
269
+ return MugMeta.from_bytes(bytes(await self._read(MugCharacteristic.MUG_ID)))
270
270
 
271
271
  async def get_battery(self) -> BatteryInfo:
272
272
  """Get Battery percent from mug gatt."""
273
- return BatteryInfo.from_bytes(await self._read(MugCharacteristic.BATTERY))
273
+ return BatteryInfo.from_bytes(bytes(await self._read(MugCharacteristic.BATTERY)))
274
274
 
275
275
  async def make_writable(self) -> bool:
276
276
  """Try to make device writable if need be."""
@@ -419,7 +419,7 @@ class EmberMug:
419
419
 
420
420
  async def get_firmware(self) -> MugFirmwareInfo:
421
421
  """Get firmware info."""
422
- return MugFirmwareInfo.from_bytes(await self._read(MugCharacteristic.FIRMWARE))
422
+ return MugFirmwareInfo.from_bytes(bytes(await self._read(MugCharacteristic.FIRMWARE)))
423
423
 
424
424
  async def update_initial(self) -> list[Change]:
425
425
  """Update attributes that don't normally change and don't need to be regularly updated."""
@@ -5,7 +5,7 @@ from __future__ import annotations
5
5
  import asyncio
6
6
  import contextlib
7
7
  import logging
8
- from typing import TYPE_CHECKING, cast
8
+ from typing import TYPE_CHECKING
9
9
 
10
10
  from bleak import BleakScanner
11
11
 
@@ -14,13 +14,14 @@ from .consts import DEVICE_SERVICE_UUIDS, IS_LINUX
14
14
  if TYPE_CHECKING:
15
15
  from typing import NotRequired, TypedDict
16
16
 
17
+ from bleak import BlueZScannerArgs
17
18
  from bleak.backends.device import BLEDevice
18
19
  from bleak.backends.scanner import AdvertisementData
19
20
 
20
- class ScannerKwargs(TypedDict):
21
+ class BleakScannerKwargs(TypedDict):
21
22
  """Optional kwargs for scanner."""
22
23
 
23
- adapter: NotRequired[str]
24
+ bluez: NotRequired[BlueZScannerArgs]
24
25
  service_uuids: NotRequired[list[str]]
25
26
 
26
27
 
@@ -29,13 +30,17 @@ DEFAULT_TIMEOUT = 30
29
30
  logger = logging.getLogger(__name__)
30
31
 
31
32
 
32
- def build_scanner_kwargs(adapter: str | None = None, *, service_uuids: list[str] | None = None) -> ScannerKwargs:
33
+ def build_scanner_kwargs(adapter: str | None = None, *, service_uuids: list[str] | None = None) -> BleakScannerKwargs:
33
34
  """Add Adapter to kwargs for scanner if specified and using BlueZ."""
34
35
  if adapter and IS_LINUX is not True:
35
36
  msg = "The adapter option is only valid for the Linux BlueZ Backend."
36
37
  raise ValueError(msg)
37
- kwargs = {"service_uuids": service_uuids} if service_uuids else {}
38
- return cast("ScannerKwargs", kwargs | {"adapter": adapter} if adapter else kwargs)
38
+ kwargs: BleakScannerKwargs = {}
39
+ if service_uuids:
40
+ kwargs |= {"service_uuids": service_uuids}
41
+ if adapter:
42
+ kwargs |= {"bluez": {"adapter": adapter}}
43
+ return kwargs
39
44
 
40
45
 
41
46
  async def discover_devices(
@@ -17,8 +17,8 @@ classifiers = [
17
17
  'Programming Language :: Python :: 3.14',
18
18
  ]
19
19
  dependencies = [
20
- "bleak-retry-connector>=4.0.2",
21
- "bleak>=1.0.1,<2.2.0",
20
+ "bleak-retry-connector>=4.6.0",
21
+ "bleak>=3.0.2",
22
22
  ]
23
23
 
24
24
  [project.optional-dependencies]
@@ -76,13 +76,14 @@ features = ["test"]
76
76
 
77
77
  [[tool.hatch.envs.test.matrix]]
78
78
  python = ["3.11", "3.12", "3.13", "3.14"]
79
+ bleak = ["3.0.2"]
79
80
 
80
81
  [tool.hatch.envs.test.scripts]
81
82
  cov = "pytest -vvv --asyncio-mode=auto --cov=ember_mug --cov-branch --cov-report=xml --cov-report=term-missing tests"
82
83
  no-cov = "cov --no-cov"
83
84
 
84
85
  [tool.hatch.envs.docs]
85
- python = "3.13"
86
+ python = "3.14"
86
87
  features = ["docs"]
87
88
 
88
89
  [tool.hatch.envs.docs.scripts]