Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- Added an optional `client` argument to `IdasenDesk.__init__` for
injecting a pre-configured `BleakClient`. Useful for downstream
wrappers that manage their own connection lifecycle (e.g. via
`bleak-retry-connector`). When provided, `disconnected_callback`
is ignored.

## [0.13.0] - 2026-05-25
### Fixed
- Fixed the CLI ignoring the `XDG_CONFIG_HOME` environment variable.
Expand Down
22 changes: 17 additions & 5 deletions idasen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,15 @@ class IdasenDesk:
disconnected_callback:
Callback that will be scheduled in the event loop when the client is
disconnected. The callable must take one argument, which will be
this client object.
this client object. Ignored when ``client`` is provided; in that
case the caller is responsible for configuring the disconnected
callback on the injected client.
client:
Optional pre-configured :class:`bleak.BleakClient` to use instead
of letting :class:`IdasenDesk` create one internally. Useful for
downstream wrappers that manage their own connection lifecycle
(e.g. via ``bleak-retry-connector``). When provided,
``disconnected_callback`` is ignored.

Note:
There is no locking to prevent you from running multiple movement
Expand Down Expand Up @@ -124,12 +132,16 @@ def __init__(
mac: Union[BLEDevice, str],
exit_on_fail: bool = False,
disconnected_callback: Optional[Callable[[BleakClient], None]] = None,
client: Optional[BleakClient] = None,
):
self._exit_on_fail = exit_on_fail
self._client = BleakClient(
address_or_ble_device=mac,
disconnected_callback=disconnected_callback,
)
if client is None:
self._client = BleakClient(
address_or_ble_device=mac,
disconnected_callback=disconnected_callback,
)
else:
self._client = client
self._mac = mac.address if isinstance(mac, BLEDevice) else mac
self._logger = _DeskLoggingAdapter(
logger=logging.getLogger(__name__), extra={"mac": self.mac}
Expand Down
29 changes: 29 additions & 0 deletions tests/test_idasen.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,35 @@ def test_mac(desk: IdasenDesk):
assert desk.mac == desk_mac


def test_init_creates_default_client():
"""Without ``client``, ``__init__`` creates its own ``BleakClient``."""
desk = IdasenDesk(mac=desk_mac)
assert isinstance(desk._client, bleak.BleakClient)


def test_init_uses_injected_client():
"""An injected ``client`` is used as-is, with no replacement."""
injected = MockBleakClient()
desk = IdasenDesk(mac=desk_mac, client=injected) # type: ignore[arg-type]
assert desk._client is injected


def test_init_ignores_disconnected_callback_when_client_provided():
"""``disconnected_callback`` is ignored when ``client`` is provided.

The caller is expected to configure the disconnected callback on the
client they pass in.
"""
injected = MockBleakClient()
callback = mock.Mock()
desk = IdasenDesk(
mac=desk_mac,
client=injected, # type: ignore[arg-type]
disconnected_callback=callback,
)
assert desk._client is injected


async def test_pair(desk: IdasenDesk):
if desk_mac != "AA:AA:AA:AA:AA:AA":
return
Expand Down