Move app-only dependencies to an optional extra (aiohttp, click, prompt_toolkit, prettytable, humanize, tomli)
- 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
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