Skip to content

bleak: cache BleakAdapter instances per event loop#1981

Open
Vodur wants to merge 1 commit into
hbldh:developfrom
Vodur:bleak-adapter-singleton
Open

bleak: cache BleakAdapter instances per event loop#1981
Vodur wants to merge 1 commit into
hbldh:developfrom
Vodur:bleak-adapter-singleton

Conversation

@Vodur
Copy link
Copy Markdown
Contributor

@Vodur Vodur commented May 5, 2026

BleakAdapter.get() now returns the same BleakAdapter instance on repeated calls from the same event loop with the same adapter selection. The cache is keyed by (loop, PlatformBleakAdapter, adapter_path), so different adapters selected via bluez={"adapter": ...} get distinct instances.

Mirrors the pattern in bleak.backends.bluezdbus.manager._global_instances introduced in 1be914c.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 5, 2026

Codecov Report

❌ Patch coverage is 87.50000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.64%. Comparing base (ae2f589) to head (db24ab2).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
bleak/__init__.py 86.66% 1 Missing and 1 partial ⚠️
bleak/backends/adapter.py 75.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #1981      +/-   ##
===========================================
+ Coverage    52.45%   52.64%   +0.19%     
===========================================
  Files           43       43              
  Lines         4097     4118      +21     
  Branches       504      505       +1     
===========================================
+ Hits          2149     2168      +19     
- Misses        1817     1819       +2     
  Partials       131      131              
Flag Coverage Δ
bluez-integration-py310 39.38% <87.50%> (+0.23%) ⬆️
bluez-integration-py311 39.38% <87.50%> (+0.23%) ⬆️
bluez-integration-py312 39.41% <87.50%> (+0.26%) ⬆️
bluez-integration-py313 39.38% <87.50%> (+0.23%) ⬆️
bluez-integration-py314 37.89% <87.50%> (+0.25%) ⬆️
macos-latest-py310 20.05% <29.16%> (+0.01%) ⬆️
macos-latest-py311 20.05% <29.16%> (+0.01%) ⬆️
macos-latest-py312 20.05% <29.16%> (+0.01%) ⬆️
macos-latest-py313 20.05% <29.16%> (+0.01%) ⬆️
macos-latest-py314 19.87% <29.16%> (+0.02%) ⬆️
ubuntu-latest-py310 24.04% <45.83%> (+0.09%) ⬆️
ubuntu-latest-py311 24.04% <45.83%> (+0.09%) ⬆️
ubuntu-latest-py312 24.04% <45.83%> (+0.09%) ⬆️
ubuntu-latest-py313 24.04% <45.83%> (+0.09%) ⬆️
ubuntu-latest-py314 22.16% <45.83%> (+0.10%) ⬆️
windows-latest-py310 18.74% <29.16%> (+0.02%) ⬆️
windows-latest-py311 18.74% <29.16%> (+0.02%) ⬆️
windows-latest-py312 18.74% <29.16%> (+0.02%) ⬆️
windows-latest-py313 18.74% <29.16%> (+0.02%) ⬆️
windows-latest-py314 18.47% <29.16%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment thread bleak/__init__.py Outdated
Comment thread tests/test_adapter_singleton.py Outdated
Comment thread tests/test_adapter_singleton.py Outdated
Comment thread tests/test_adapter_singleton.py Outdated
Comment thread tests/test_adapter_singleton.py Outdated
Comment thread tests/test_adapter_singleton.py Outdated
Comment thread tests/test_adapter_singleton.py Outdated
Comment thread CHANGELOG.rst Outdated
@Vodur Vodur force-pushed the bleak-adapter-singleton branch 2 times, most recently from dcceced to 7fde0a3 Compare May 5, 2026 16:59
@Vodur
Copy link
Copy Markdown
Contributor Author

Vodur commented May 5, 2026

Three CI failures from trying real BleakAdapter.get():

  • macOS (build_desktop): BleakBluetoothNotAvailableError: Bluetooth is unsupported - runner has no BT hardware
  • Linux (build_desktop): BleakDBusError: org.bluez was not provided by any .service files - bluetoothd not installed
  • Linux Alpine VM (integration_tests_bluez): BleakBluetoothNotAvailableError: No Bluetooth adapters found - VHCI is per-fixture, not active when our tests run

Real BleakAdapter.get() only works inside integration tests that have already set up their BT environment. So I switched to fake BaseBleakAdapter subclasses for unit tests. Real platform behavior is exercised by tests/integration/test_adapter.py.

Also added the cache_key classmethod (default None, BlueZ overrides to bluez["adapter"]) instead of the name-string check.

Force-pushed 7fde0a3.

@dlech
Copy link
Copy Markdown
Collaborator

dlech commented May 5, 2026

I don't understand why we can't put the tests in the integration tests and avoid mocking the BaseBleakAdapter.

@dlech
Copy link
Copy Markdown
Collaborator

dlech commented May 5, 2026

I don't understand why we can't put the tests in the integration tests and avoid mocking the BaseBleakAdapter.

Other than the special case of BlueZ with more than one adapter being used by Bleak at the same time.

@Vodur Vodur force-pushed the bleak-adapter-singleton branch from 7fde0a3 to e8f3dae Compare May 6, 2026 04:30
@Vodur
Copy link
Copy Markdown
Contributor Author

Vodur commented May 6, 2026

Moved both tests to tests/integration/test_adapter.py using the existing hci_transport fixture - no fakes, real BleakAdapter.get(). The differentiation test for the multi-adapter case doesn't need two VHCIs: BleakAdapterBlueZDBus.get() doesn't validate the adapter name (just builds the D-Bus path string), so two arbitrary strings via bluez={"adapter": ...} are enough to verify the cache-key dispatch.

@Vodur Vodur force-pushed the bleak-adapter-singleton branch from e8f3dae to da4920c Compare May 6, 2026 10:01
@dlech
Copy link
Copy Markdown
Collaborator

dlech commented May 6, 2026

so two arbitrary strings via bluez={"adapter": ...} are enough to verify the cache-key dispatch.

I would expect calling BleakAdapter.get(bluez={"adapter": "junk"}) should fail with an error that says that the adapter does not exist. So how could that test work? (I didn't look at the code yet.)

@Vodur
Copy link
Copy Markdown
Contributor Author

Vodur commented May 6, 2026

so two arbitrary strings via bluez={"adapter": ...} are enough to verify the cache-key dispatch.

I would expect calling BleakAdapter.get(bluez={"adapter": "junk"}) should fail with an error that says that the adapter does not exist. So how could that test work? (I didn't look at the code yet.)

Right - currently BleakAdapterBlueZDBus.get() doesn't validate the adapter name (you noted on #1979 that we'd defer fixing it). The test passes because of that, not because cache-key dispatch is being meaningfully exercised.

Easiest path: drop the differentiation test from this PR.

@Vodur Vodur force-pushed the bleak-adapter-singleton branch from da4920c to 0d007b6 Compare May 6, 2026 14:56
Comment thread bleak/backends/bluezdbus/adapter.py
Comment thread bleak/backends/bluezdbus/adapter.py Outdated
Comment thread bleak/backends/adapter.py Outdated
Comment thread bleak/__init__.py Outdated
@Vodur Vodur force-pushed the bleak-adapter-singleton branch from 0d007b6 to 68093f7 Compare May 9, 2026 18:36
Comment thread bleak/__init__.py Outdated
Comment thread tests/integration/test_adapter.py Outdated
@Vodur
Copy link
Copy Markdown
Contributor Author

Vodur commented May 10, 2026

Tried @final first but pyright doesn't narrow self to BleakAdapter even on a final class, so the cast was still needed. Went with changing the return type from self to "BleakAdapter" since the class is final - but that's a public-signature change you didn't actually ask for.

@Vodur Vodur force-pushed the bleak-adapter-singleton branch from 68093f7 to 96a44a7 Compare May 10, 2026 04:00
@Vodur Vodur requested a review from dlech May 23, 2026 14:57
BleakAdapter.get() now returns the same BleakAdapter instance on repeated calls from the same event loop with the same adapter selection. The cache is keyed by (loop, PlatformBleakAdapter, cache_key), where cache_key is supplied by each backend (BlueZ uses bluez['adapter'] to differentiate; other backends return None for a single cache entry per loop).

Mirrors the pattern in bleak.backends.bluezdbus.manager._global_instances introduced in 1be914c.
@Vodur Vodur force-pushed the bleak-adapter-singleton branch from 96a44a7 to db24ab2 Compare June 1, 2026 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants