From adef270195807f7b0a17778c65d9a35948ec4853 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Sat, 7 Mar 2026 01:33:28 +0800 Subject: [PATCH] Refine dependencies --- .devcontainer/devcontainer.json | 2 +- .github/workflows/code-check.yml | 2 +- .github/workflows/python-avatar.yml | 2 +- .github/workflows/python-build-test.yml | 4 +- README.md | 2 +- apps/auracast.py | 4 +- apps/lea_unicast/app.py | 2 +- bumble/transport/android_emulator.py | 19 ++++--- bumble/transport/android_netsim.py | 33 +++++++---- docs/mkdocs/src/apps_and_tools/auracast.md | 6 +- docs/mkdocs/src/getting_started.md | 6 ++ docs/mkdocs/src/platforms/android.md | 14 +++++ .../mkdocs/src/transports/android_emulator.md | 3 + pyproject.toml | 55 ++++++++++++------- tasks.py | 2 +- 15 files changed, 102 insertions(+), 54 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 92ebdab1f..9535f4245 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -12,7 +12,7 @@ // Use 'postCreateCommand' to run commands after the container is created. "postCreateCommand": - "python -m pip install '.[build,test,development,documentation]'", + "python -m pip install '.[all]' --group dev", // Configure tool-specific properties. "customizations": { diff --git a/.github/workflows/code-check.yml b/.github/workflows/code-check.yml index 9f24fcdf0..20782e1c7 100644 --- a/.github/workflows/code-check.yml +++ b/.github/workflows/code-check.yml @@ -35,7 +35,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install ".[build,test,development]" + python -m pip install ".[all]" --group dev - name: Check run: | invoke project.pre-commit diff --git a/.github/workflows/python-avatar.yml b/.github/workflows/python-avatar.yml index 60a6aeda0..46b5bc3ab 100644 --- a/.github/workflows/python-avatar.yml +++ b/.github/workflows/python-avatar.yml @@ -34,7 +34,7 @@ jobs: - name: Install run: | python -m pip install --upgrade pip - python -m pip install .[avatar] + python -m pip install .[all,avatar] - name: Rootcanal run: nohup python -m rootcanal > rootcanal.log & - name: Test diff --git a/.github/workflows/python-build-test.yml b/.github/workflows/python-build-test.yml index 41632d713..efdc7457f 100644 --- a/.github/workflows/python-build-test.yml +++ b/.github/workflows/python-build-test.yml @@ -35,7 +35,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install ".[build,test,development,documentation]" + python -m pip install ".[all]" --group dev - name: Test run: | invoke test @@ -62,7 +62,7 @@ jobs: - name: Install Python dependencies run: | python -m pip install --upgrade pip - python -m pip install ".[build,test,development,documentation]" + python -m pip install ".[all]" --group dev - name: Install Rust toolchain uses: actions-rust-lang/setup-rust-toolchain@v1 with: diff --git a/README.md b/README.md index 43e3c6420..cbd4ebf41 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ To install package dependencies needed to run the bumble examples, execute the f ``` python -m pip install --upgrade pip -python -m pip install ".[test,development,documentation]" +python -m pip install ".[all]" --group dev ``` ### Examples diff --git a/apps/auracast.py b/apps/auracast.py index 59cedbbd3..a886e3425 100644 --- a/apps/auracast.py +++ b/apps/auracast.py @@ -40,9 +40,7 @@ try: import lc3 # type: ignore # pylint: disable=E0401 except ImportError as e: - raise ImportError( - "Try `python -m pip install \"git+https://github.com/google/liblc3.git\"`." - ) from e + raise ImportError("Try `python -m pip install '.[auracast]'`.") from e import bumble.device import bumble.logging diff --git a/apps/lea_unicast/app.py b/apps/lea_unicast/app.py index 4e31c0eb1..d821c9a78 100644 --- a/apps/lea_unicast/app.py +++ b/apps/lea_unicast/app.py @@ -30,7 +30,7 @@ try: import lc3 # type: ignore # pylint: disable=E0401 except ImportError as e: - raise ImportError("Try `python -m pip install \".[lc3]\"`.") from e + raise ImportError("Try `python -m pip install \".[auracast]\"`.") from e import aiohttp.web import click diff --git a/bumble/transport/android_emulator.py b/bumble/transport/android_emulator.py index fe0a0fbe5..fd68f192b 100644 --- a/bumble/transport/android_emulator.py +++ b/bumble/transport/android_emulator.py @@ -28,13 +28,18 @@ ) # pylint: disable=no-name-in-module -from bumble.transport.grpc_protobuf.emulated_bluetooth_packets_pb2 import HCIPacket -from bumble.transport.grpc_protobuf.emulated_bluetooth_pb2_grpc import ( - EmulatedBluetoothServiceStub, -) -from bumble.transport.grpc_protobuf.emulated_bluetooth_vhci_pb2_grpc import ( - VhciForwardingServiceStub, -) +try: + from bumble.transport.grpc_protobuf.emulated_bluetooth_packets_pb2 import HCIPacket + from bumble.transport.grpc_protobuf.emulated_bluetooth_pb2_grpc import ( + EmulatedBluetoothServiceStub, + ) + from bumble.transport.grpc_protobuf.emulated_bluetooth_vhci_pb2_grpc import ( + VhciForwardingServiceStub, + ) +except ImportError as e: + raise ImportError( + 'The bumble[android] extra is required to use the Android emulator transport' + ) from e # ----------------------------------------------------------------------------- # Logging diff --git a/bumble/transport/android_netsim.py b/bumble/transport/android_netsim.py index e53bd6023..375f57d7c 100644 --- a/bumble/transport/android_netsim.py +++ b/bumble/transport/android_netsim.py @@ -37,18 +37,27 @@ ) # pylint: disable=no-name-in-module -from bumble.transport.grpc_protobuf.netsim.common_pb2 import ChipKind -from bumble.transport.grpc_protobuf.netsim.hci_packet_pb2 import HCIPacket -from bumble.transport.grpc_protobuf.netsim.packet_streamer_pb2 import ( - PacketRequest, - PacketResponse, -) -from bumble.transport.grpc_protobuf.netsim.packet_streamer_pb2_grpc import ( - PacketStreamerServicer, - PacketStreamerStub, - add_PacketStreamerServicer_to_server, -) -from bumble.transport.grpc_protobuf.netsim.startup_pb2 import Chip, ChipInfo, DeviceInfo +try: + from bumble.transport.grpc_protobuf.netsim.common_pb2 import ChipKind + from bumble.transport.grpc_protobuf.netsim.hci_packet_pb2 import HCIPacket + from bumble.transport.grpc_protobuf.netsim.packet_streamer_pb2 import ( + PacketRequest, + PacketResponse, + ) + from bumble.transport.grpc_protobuf.netsim.packet_streamer_pb2_grpc import ( + PacketStreamerServicer, + PacketStreamerStub, + add_PacketStreamerServicer_to_server, + ) + from bumble.transport.grpc_protobuf.netsim.startup_pb2 import ( + Chip, + ChipInfo, + DeviceInfo, + ) +except ImportError as e: + raise ImportError( + 'The bumble[android] extra is required to use the Android netsim transport' + ) from e # ----------------------------------------------------------------------------- # Logging diff --git a/docs/mkdocs/src/apps_and_tools/auracast.md b/docs/mkdocs/src/apps_and_tools/auracast.md index 754215a4a..6d0af9498 100644 --- a/docs/mkdocs/src/apps_and_tools/auracast.md +++ b/docs/mkdocs/src/apps_and_tools/auracast.md @@ -29,10 +29,10 @@ Try installing the optional `[auracast]` dependencies: ## LC3 The `auracast` app depends on the `lc3` python module, which is available -either as PyPI module (currently only available for Linux x86_64). +as a PyPI module `lc3py` (currently available for Linux x86_64 and macOS arm64). When installing Bumble with the optional `auracast` dependency, the `lc3` -module will be installed from the `lc3py` PyPI package if available. -If not, you will need to install it separately. This can be done with: +module will be installed automatically if your platform is supported. +If not, you will need to install it separately. This can be done by building it from source: ```bash $ python3 -m pip install "git+https://github.com/google/liblc3.git" ``` diff --git a/docs/mkdocs/src/getting_started.md b/docs/mkdocs/src/getting_started.md index 960e37f75..bdd297c65 100644 --- a/docs/mkdocs/src/getting_started.md +++ b/docs/mkdocs/src/getting_started.md @@ -71,6 +71,12 @@ $ python3 -m pip install git+https://github.com/google/bumble.git@27c0551 When you work on the Bumble code itself, and run some of the tests or example apps, or import the module in your own code, you typically either install the package from source in "development mode" as described above, or you may choose to skip the install phase. +!!! tip "Installing Development Dependencies" + To install all optional dependencies and development tools (like `pytest`, `black`, `invoke`, etc.), run: + ```bash + python3 -m pip install -e ".[all]" --group dev + ``` + If you plan on contributing to the project, please read the [contributing](development/contributing.md) section. ## Without Installing diff --git a/docs/mkdocs/src/platforms/android.md b/docs/mkdocs/src/platforms/android.md index 02d726f23..617b7263d 100644 --- a/docs/mkdocs/src/platforms/android.md +++ b/docs/mkdocs/src/platforms/android.md @@ -24,6 +24,20 @@ stack via a virtual HCI interface. Both ways are controlled via gRPC requests to the Android emulator controller and/or from the Android emulator. +## Prerequisites + +Using the Android Emulator or Netsim transports requires the `android` optional dependencies (which include `grpcio` and `protobuf`). + +If you installed Bumble from PyPI: +```bash +python3 -m pip install "bumble[android]" +``` + +If you are running from source: +```bash +python3 -m pip install ".[android]" +``` + ## Launching the Emulator If the version of the emulator you are running does not yet support enabling diff --git a/docs/mkdocs/src/transports/android_emulator.md b/docs/mkdocs/src/transports/android_emulator.md index becff5414..0e24a83b4 100644 --- a/docs/mkdocs/src/transports/android_emulator.md +++ b/docs/mkdocs/src/transports/android_emulator.md @@ -8,6 +8,9 @@ ANDROID EMULATOR TRANSPORT Use the `android-netsim` transport name instead. +!!! note + This transport requires the `android` extra. See the [Android Platform](../platforms/android.md) page for installation instructions. + The Android "netsim" transport either connects, as a host, to a **Netsim** virtual controller ("host" mode), or acts as a virtual controller itself ("controller" mode) accepting host connections. diff --git a/pyproject.toml b/pyproject.toml index de4607947..9692286a8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,23 +24,42 @@ dependencies = [ # updated. Relax the version requirement since it's better than being completely unable # to import the package in case of version mismatch. "cryptography >= 42.0.8; platform_system=='Android'", - "grpcio >= 1.62.1; platform_system!='Emscripten'", "humanize >= 4.6.0; platform_system!='Emscripten'", - "libusb1 >= 2.0.1; platform_system!='Emscripten'", - "libusb-package == 1.0.26.4; platform_system!='Emscripten' and platform_system!='Android'", "platformdirs >= 3.10.0; platform_system!='Emscripten'", "prompt_toolkit >= 3.0.16; platform_system!='Emscripten'", "prettytable >= 3.6.0; platform_system!='Emscripten'", - "protobuf >= 3.12.4; platform_system!='Emscripten'", "pyee >= 13.0.0", + "tomli ~= 2.2.1; platform_system!='Emscripten' and python_version<'3.11'", + "websockets >= 15.0.1; platform_system!='Emscripten'", + # Serial "pyserial-asyncio >= 0.5; platform_system!='Emscripten'", "pyserial >= 3.5; platform_system!='Emscripten'", + # USB + "libusb1 >= 2.0.1; platform_system!='Emscripten'", + "libusb-package == 1.0.26.4; platform_system!='Emscripten' and platform_system!='Android'", "pyusb >= 1.2; platform_system!='Emscripten'", - "tomli ~= 2.2.1; platform_system!='Emscripten' and python_version<'3.11'", - "websockets >= 15.0.1; platform_system!='Emscripten'", ] [project.optional-dependencies] +android = [ + "grpcio >= 1.62.1; platform_system!='Emscripten'", + "protobuf >= 3.12.4; platform_system!='Emscripten'", +] +avatar = [ + "pandora-avatar == 0.0.10", + "rootcanal == 1.11.1 ; python_version>='3.10'", +] +pandora = ["bt-test-interfaces >= 0.0.6"] +auracast = [ + "lc3py >= 1.1.3; python_version>='3.10' and ((platform_system=='Linux' and platform_machine=='x86_64') or (platform_system=='Darwin' and platform_machine=='arm64'))", + "sounddevice >= 0.5.1", +] +all = [ + "bumble[android]", + "bumble[auracast]", +] + +[dependency-groups] build = ["build >= 0.7"] test = [ "pytest >= 9.0", @@ -48,7 +67,15 @@ test = [ "pytest-html >= 4.2", "coverage >= 6.4", ] -development = [ +docs = [ + "mkdocs >= 1.6.0", + "mkdocs-material >= 9.6", + "mkdocstrings[python] >= 0.27.0", +] +dev = [ + {include-group = "build"}, + {include-group = "test"}, + {include-group = "docs"}, "black ~= 25.1", "bt-test-interfaces >= 0.0.6", "grpcio-tools >= 1.62.1", @@ -63,20 +90,6 @@ development = [ "types-invoke >= 1.7.3", "types-protobuf >= 4.21.0", ] -avatar = [ - "pandora-avatar == 0.0.10", - "rootcanal == 1.11.1 ; python_version>='3.10'", -] -pandora = ["bt-test-interfaces >= 0.0.6"] -documentation = [ - "mkdocs >= 1.6.0", - "mkdocs-material >= 9.6", - "mkdocstrings[python] >= 0.27.0", -] -auracast = [ - "lc3py >= 1.1.3; python_version>='3.10' and ((platform_system=='Linux' and platform_machine=='x86_64') or (platform_system=='Darwin' and platform_machine=='arm64'))", - "sounddevice >= 0.5.1", -] [project.scripts] bumble-auracast = "bumble.apps.auracast:main" diff --git a/tasks.py b/tasks.py index f0490f096..d42dc3696 100644 --- a/tasks.py +++ b/tasks.py @@ -47,7 +47,7 @@ def build(ctx, install=False): if install: ctx.run('python -m pip install .[build]') - ctx.run("python -m build") + ctx.run("python -I -m build") # -----------------------------------------------------------------------------