google / google/bumble

Move app-only dependencies to an optional extra (aiohttp, click, prompt_toolkit, prettytable, humanize, tomli)

Open
#966 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
555
Forks
138
Avg merge
3d 15h
Merged PRs (30d)
9

Description

### Summary

Six runtime dependencies are only imported by the bundled apps and tools, never by the
library itself. Installing `bumble` to use it as a Bluetooth stack currently also installs a
web server, a CLI framework, and a terminal UI toolkit.

Would you consider moving them behind an optional extra, e.g. `bumble[apps]`?

### Detail

Checked against 0.0.233, counting files that import each module under `bumble/` versus
`apps/` + `tools/`:

| Dependency | core | apps/tools |
|---|---|---|
| `click` | 0 | 24 |
| `aiohttp` | 0 | 2 |
| `prompt_toolkit` | 0 | 2 |
| `prettytable` | 0 | 1 |
| `humanize` | 0 | 1 |
| `tomli` | 0 | 1 |

`aiohttp` is the one that prompted this. It is used only by `apps/speaker/speaker.py` and
`apps/lea_unicast/app.py`, both for `aiohttp.web` to serve a browser UI. We consume bumble
purely as a library (`bumble.device`, `bumble.hci`, `bumble.gatt`, `bumble.transport`, …) and
never import `bumble.apps`, but we still had to resolve a high-severity `aiohttp` advisory
(GHSA-cq5v-8q36-5273) in our lockfile because it is a transitive pin. Dependency scanners look
at the lockfile, not the call graph.

### Why it matters

* Supply-chain surface: a BLE library pulls in an HTTP server and its dependency tree.
* Security churn: advisories in app-only packages become work for every downstream consumer.
* Install weight for embedded/CI environments that only need the stack.

### Suggested shape

The project already uses optional dependencies for `android` and `auracast`, so this would
follow the existing pattern:

```toml
[project.optional-dependencies]
apps = [
"aiohttp ~= 3.8; platform_system!='Emscripten'",
"click >= 8.1.3; platform_system!='Emscripten'",
"prompt_toolkit >= 3.0.16; platform_system!='Emscripten'",
"prettytable >= 3.6.0; platform_system!='Emscripten'",
"humanize >= 4.6.0; platform_system!='Emscripten'",
"tomli ~= 2.2.1; platform_system!='Emscripten' and python_version<'3.11'",
]
all = ["bumble[android]", "bumble[auracast]", "bumble[apps]"]
pip install bumble gets the stack; pip install bumble[apps] gets the demos and CLI tools.

The obvious objection
[project.scripts] declares ~20 console scripts pointing at bumble.apps.*, so a bare
install would still create the entry points but they would fail on import. Options, roughly in
order of effort:

1. Document it, and let the ImportError speak for itself.
2. Have the app entry points catch ImportError and print "install bumble[apps] to use this tool".
3. Move the scripts under the extra too, if the packaging tooling allows it cleanly.

Happy to send a PR for whichever shape you prefer, if this is something you would take.

Contributor guide

Open the contributing guide

Research direction

Start with the existing optional-dependency declarations for android and auracast, then review the project.scripts entry points and imports in apps/speaker/speaker.py and apps/lea_unicast/app.py. Compare the remaining apps/tools imports with the six listed dependencies. Done means the base install excludes them, bumble[apps] supports the apps and tools, and bare entry points have an intentional documented behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
build-system, tooling
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.