Skip to content

Conversation

@timrid
Copy link
Contributor

@timrid timrid commented Oct 13, 2025

Currently the backend detection logic is duplicated in bleak.backends.client and bleak.backends.scanner. This PR centralizes the backend detection and added a new BleakBackend enum.

This additional BleakBackend has also the benefit for #1838 to simplify the conditional test execution depending on the detected backend.

@timrid timrid mentioned this pull request Oct 13, 2025
Copy link
Collaborator

@dlech dlech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a suggestion, we could take this one step farther. Instead of creating an enum class, we could create a BackendProvider class that has two attributes, the scanner_type and client_type. Then we could remove the two get_platform_{client,scanner}_backend_type() functions completely and just use the new get_backend() (or get_backend_provider() function to replace that.

That is, replace:

PlatformBleakClient = (
            get_platform_client_backend_type() if backend is None else backend
        )

with

PlatformBleakClient = (
            get_backend_provider().client_type if backend is None else backend
        )

P4Android = enum.auto()
BlueZDBus = enum.auto()
PythonistaCB = enum.auto()
CoreBluetooth = enum.auto()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be tempted to call this one PyObjCCB since we are looking at adding a Rubicon ObjC backend as well.

It is kind of a special case since we would have two backends sharing code, so maybe you had something else in mind?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would differentiate bleak backends and the binding frameworks. The bleak backend is CoreBluetooth, the binding frameworks for this backend are pyobjc or rubicon-objc.

In my currently local testing for rubicon-objc the most code for CoreBluetooth is shared. So I don’t think that it should be listed as a complete new backend. The detection logic which binding framework is used can be inside the CoreBluetooth backend itself.

@dlech
Copy link
Collaborator

dlech commented Oct 19, 2025

As a suggestion, we could take this one step farther.

Not sure how clear I was on this and it was pretty simple anyway, so I went ahead and tried it myself in #1845.

@timrid
Copy link
Contributor Author

timrid commented Oct 19, 2025

As a suggestion, we could take this one step farther.

Not sure how clear I was on this and it was pretty simple anyway, so I went ahead and tried it myself in #1845.

So, your PR #1845 is providing only a solution for the code deduplication.

But my second intention of this PR was to provide an BleakBackend enum that can be used to selectively run/skip tests for some backends in #1838 . See here for example.

@dlech
Copy link
Collaborator

dlech commented Oct 19, 2025

But my second intention of this PR was to provide an BleakBackend enum that can be used to selectively run/skip tests f

Ah-ha. That could be useful as well at runtime to help handle platform-specific quirks.

@timrid timrid force-pushed the centralize-backend-detection branch from 1ca33bd to 9200840 Compare October 19, 2025 22:52
@dlech
Copy link
Collaborator

dlech commented Oct 25, 2025

I still have a small hesitation before merging this. There are some 3rd-party backends for Bleak. These get passed into the BleakClient() and BleakScanner() constructors. So it is possible for an application to use multiple backends at the same time. The means that the backend returned by the new get_backend() function is not necessarily the backend use by a specific BleakClient object. This makes me a little bit worried that someone could write a library that uses the new APIs to control behavior based on the assumed backend, only to find out later that someone is using a different backend that doesn't have the same behavior.

Up to now, this is the recommended way to get the actual backend:

if client._backend.__class__.__name__ == "BleakClientBlueZDBus": # type: ignore

@timrid
Copy link
Contributor Author

timrid commented Oct 26, 2025

To use client._backend.__class__.__name__ looks more like a workaround than an official way to check the backend. But I see your point, that you can have a BleakClient or BleakScanner that uses a custom backend.

I implemented the following changes:

  • I renamed get_backend to get_default_backend to make it more clear that this is only the default backend and not the one that is enforced for a BleakClient or BleakScanner.
  • I added a backend_id parameter for BleakClient and BleakScanner that returns the enum to the current backend (or a string for a custom backend).

@timrid timrid requested a review from dlech October 26, 2025 21:25
Copy link
Collaborator

@dlech dlech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update. I'm happy with the changes. Just a few more minor suggestions before we merge.

@dlech
Copy link
Collaborator

dlech commented Nov 4, 2025

#1855 should fix the failing tests here.

@dlech
Copy link
Collaborator

dlech commented Nov 5, 2025

I added a bit to make the new stuff actually show up in the docs.

Ready to merge now, thanks!

@dlech dlech merged commit a6fea5a into hbldh:develop Nov 5, 2025
16 checks passed
@timrid timrid deleted the centralize-backend-detection branch November 7, 2025 19:53
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