python-ember-mug 1.1.1__tar.gz → 1.2.0b1__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.
Files changed (28) hide show
  1. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/PKG-INFO +3 -1
  2. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/ember_mug/__init__.py +1 -1
  3. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/ember_mug/consts.py +2 -2
  4. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/ember_mug/scanner.py +13 -5
  5. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/ember_mug/utils.py +1 -1
  6. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/pyproject.toml +3 -2
  7. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/tests/cli/test_commands.py +2 -2
  8. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/tests/test_consts.py +8 -0
  9. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/tests/test_scanner.py +11 -3
  10. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/.gitignore +0 -0
  11. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/LICENSE +0 -0
  12. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/README.md +0 -0
  13. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/ember_mug/__main__.py +0 -0
  14. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/ember_mug/cli/__init__.py +0 -0
  15. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/ember_mug/cli/commands.py +0 -0
  16. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/ember_mug/cli/helpers.py +0 -0
  17. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/ember_mug/data.py +0 -0
  18. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/ember_mug/formatting.py +0 -0
  19. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/ember_mug/mug.py +0 -0
  20. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/tests/__init__.py +0 -0
  21. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/tests/cli/__init__.py +0 -0
  22. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/tests/cli/test_helpers.py +0 -0
  23. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/tests/conftest.py +0 -0
  24. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/tests/test_connection.py +0 -0
  25. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/tests/test_data.py +0 -0
  26. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/tests/test_formatting.py +0 -0
  27. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/tests/test_mug_data.py +0 -0
  28. {python_ember_mug-1.1.1 → python_ember_mug-1.2.0b1}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-ember-mug
3
- Version: 1.1.1
3
+ Version: 1.2.0b1
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/
@@ -20,6 +20,8 @@ Requires-Python: >=3.11
20
20
  Requires-Dist: bleak-retry-connector>=3.5.0
21
21
  Requires-Dist: bleak>=0.22.2; python_version < '3.13'
22
22
  Requires-Dist: bleak>=0.22.3; python_version <= '3.13'
23
+ Provides-Extra: dev
24
+ Requires-Dist: ipython; extra == 'dev'
23
25
  Provides-Extra: docs
24
26
  Requires-Dist: black; extra == 'docs'
25
27
  Requires-Dist: mkdocs-autorefs; extra == 'docs'
@@ -6,4 +6,4 @@ __all__ = ("EmberMug",)
6
6
 
7
7
  __author__ = """Jesse Sopel"""
8
8
  __email__ = "jesse.sopel@gmail.com"
9
- __version__ = "1.1.1"
9
+ __version__ = "1.2.0b1"
@@ -149,10 +149,10 @@ TRAVEL_MUG_SERVICE_UUIDS = (
149
149
  str(MugCharacteristic.TRAVEL_MUG_SERVICE_OTHER),
150
150
  )
151
151
 
152
- DEVICE_SERVICE_UUIDS = (
152
+ DEVICE_SERVICE_UUIDS = [
153
153
  str(MugCharacteristic.STANDARD_SERVICE),
154
154
  *TRAVEL_MUG_SERVICE_UUIDS,
155
- )
155
+ ]
156
156
 
157
157
 
158
158
  class LiquidState(IntEnum):
@@ -5,29 +5,37 @@ from __future__ import annotations
5
5
  import asyncio
6
6
  import contextlib
7
7
  import logging
8
- from typing import TYPE_CHECKING, Any
8
+ from typing import TYPE_CHECKING, cast
9
9
 
10
10
  from bleak import BleakScanner
11
11
 
12
12
  from .consts import DEVICE_SERVICE_UUIDS, IS_LINUX
13
13
 
14
14
  if TYPE_CHECKING:
15
+ from typing import NotRequired, TypedDict
16
+
15
17
  from bleak.backends.device import BLEDevice
16
18
  from bleak.backends.scanner import AdvertisementData
17
19
 
20
+ class ScannerKwargs(TypedDict):
21
+ """Optional kwargs for scanner."""
22
+
23
+ adapter: NotRequired[str]
24
+ service_uuids: NotRequired[list[str]]
25
+
18
26
 
19
27
  DEFAULT_TIMEOUT = 30
20
28
 
21
29
  logger = logging.getLogger(__name__)
22
30
 
23
31
 
24
- def build_scanner_kwargs(adapter: str | None = None) -> dict[str, Any]:
32
+ def build_scanner_kwargs(adapter: str | None = None, *, service_uuids: list[str] | None = None) -> ScannerKwargs:
25
33
  """Add Adapter to kwargs for scanner if specified and using BlueZ."""
26
34
  if adapter and IS_LINUX is not True:
27
35
  msg = "The adapter option is only valid for the Linux BlueZ Backend."
28
36
  raise ValueError(msg)
29
- kwargs = {"service_uuids": DEVICE_SERVICE_UUIDS}
30
- return kwargs | {"adapter": adapter} if adapter else kwargs
37
+ kwargs = {"service_uuids": service_uuids} if service_uuids else {}
38
+ return cast("ScannerKwargs", kwargs | {"adapter": adapter} if adapter else kwargs)
31
39
 
32
40
 
33
41
  async def discover_devices(
@@ -47,7 +55,7 @@ async def discover_devices(
47
55
  ```
48
56
 
49
57
  """
50
- async with BleakScanner(**build_scanner_kwargs(adapter)) as scanner:
58
+ async with BleakScanner(**build_scanner_kwargs(adapter, service_uuids=DEVICE_SERVICE_UUIDS)) as scanner:
51
59
  await asyncio.sleep(wait)
52
60
  return [
53
61
  (d, a)
@@ -134,7 +134,7 @@ def guess_model_from_name(name: str | None) -> DeviceModel | None:
134
134
 
135
135
  def get_model_info_from_advertiser_data(advertisement: AdvertisementData) -> ModelInfo:
136
136
  """Extract model info from manufacturer data in advertiser data."""
137
- from ember_mug.data import ModelInfo
137
+ from ember_mug.data import ModelInfo # noqa: PLC0415
138
138
 
139
139
  model_data = advertisement.manufacturer_data.get(EMBER_BLE_SIG, None)
140
140
  if model_data is not None:
@@ -1,5 +1,3 @@
1
- [tool]
2
-
3
1
  [project]
4
2
  name = "python-ember-mug"
5
3
  readme = "README.md"
@@ -43,6 +41,9 @@ docs = [
43
41
  "black",
44
42
  "termynal",
45
43
  ]
44
+ dev = [
45
+ "ipython",
46
+ ]
46
47
 
47
48
  [project.urls]
48
49
  "Changelog" = "https://sopelj.github.io/python-ember-mug/changelog/"
@@ -316,7 +316,7 @@ def test_ember_cli():
316
316
  @patch("ember_mug.consts.IS_LINUX", False)
317
317
  def test_ember_cli_windows():
318
318
  del sys.modules["ember_mug.cli.commands"] # force re-import
319
- from ember_mug.cli.commands import EmberMugCli
319
+ from ember_mug.cli.commands import EmberMugCli # noqa: PLC0415
320
320
 
321
321
  cli = EmberMugCli()
322
322
 
@@ -364,7 +364,7 @@ async def test_cli_run_discover_debug(mock_logging_config: Mock):
364
364
  @patch("sys.argv", ["file.py", "find", "-m", TEST_MAC, "--raw"])
365
365
  async def test_cli_run_non_linux():
366
366
  del sys.modules["ember_mug.cli.commands"] # force re-import
367
- from ember_mug.cli.commands import EmberMugCli
367
+ from ember_mug.cli.commands import EmberMugCli # noqa: PLC0415
368
368
 
369
369
  cli = EmberMugCli()
370
370
  mock_find = AsyncMock()
@@ -4,9 +4,17 @@ from __future__ import annotations
4
4
 
5
5
  from uuid import UUID
6
6
 
7
+ import pytest
8
+
7
9
  from ember_mug.consts import LiquidState, MugCharacteristic, VolumeLevel
8
10
 
9
11
 
12
+ @pytest.mark.parametrize("characteristic", MugCharacteristic)
13
+ def test_characteristic_uuids(characteristic: MugCharacteristic) -> None:
14
+ assert characteristic.uuid == UUID(f"fc54{characteristic.value:04x}-236c-4c94-8fa9-944a3e5353fa")
15
+ assert str(characteristic) == f"fc54{characteristic.value:04x}-236c-4c94-8fa9-944a3e5353fa"
16
+
17
+
10
18
  def test_mug_uuids() -> None:
11
19
  assert MugCharacteristic.MUG_NAME.uuid == UUID("fc540001-236c-4c94-8fa9-944a3e5353fa")
12
20
  assert str(MugCharacteristic.MUG_NAME) == "fc540001-236c-4c94-8fa9-944a3e5353fa"
@@ -1,5 +1,8 @@
1
1
  """Tests for scanner."""
2
2
 
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
3
6
  from unittest.mock import AsyncMock, MagicMock, patch
4
7
 
5
8
  import pytest
@@ -10,15 +13,20 @@ from ember_mug.scanner import build_scanner_kwargs, discover_devices, find_devic
10
13
 
11
14
  from .conftest import TEST_MUG_ADVERTISEMENT
12
15
 
16
+ if TYPE_CHECKING:
17
+ from ember_mug.scanner import ScannerKwargs
18
+
13
19
  MUG_1 = BLEDevice(address="32:36:a5:be:88:cb", name="Ember Ceramic Mug", details={}, rssi=1)
14
20
  MUG_2 = BLEDevice(address="9c:da:8c:19:27:da", name="Ember Ceramic Mug", details={}, rssi=1)
15
21
  EXAMPLE_MUGS = [MUG_1, MUG_2]
22
+ SERVICE_UUID_KWARG = {"service_uuids": DEVICE_SERVICE_UUIDS}
23
+ ADAPTER_KWARG = {"adapter": "hci0"}
16
24
 
17
25
 
18
26
  @patch("ember_mug.scanner.IS_LINUX", True)
19
- def test_build_scanner_kwargs_linux() -> None:
20
- assert build_scanner_kwargs() == {"service_uuids": DEVICE_SERVICE_UUIDS}
21
- assert build_scanner_kwargs(adapter="hci0") == {"adapter": "hci0", "service_uuids": DEVICE_SERVICE_UUIDS}
27
+ @pytest.mark.parametrize("kwargs", [{}, ADAPTER_KWARG, SERVICE_UUID_KWARG, ADAPTER_KWARG | SERVICE_UUID_KWARG])
28
+ def test_build_scanner_kwargs_linux(kwargs: ScannerKwargs) -> None:
29
+ assert build_scanner_kwargs(**kwargs) == kwargs
22
30
 
23
31
 
24
32
  @patch("ember_mug.scanner.IS_LINUX", False)