From b791bc8455aa6cb9aeb20c1c86d6c1b417488d2d Mon Sep 17 00:00:00 2001 From: Peter Corke Date: Fri, 24 Jul 2026 08:26:14 +1000 Subject: [PATCH] feat(rtbtool): add 'tool' extra for IPython/pygments, fail with clear message when missing rtbtool imported IPython, pygments, and traitlets unconditionally at module scope, but none of the three were declared as a dependency anywhere -- pip install roboticstoolbox-python followed by running rtbtool crashed with a raw ModuleNotFoundError unless IPython happened to already be present transitively (e.g. via Jupyter). Move the imports into main(), guarded by a try/except that points the user at the new 'tool' extra instead. Since rtbtool is an opt-in interactive shell rather than something every library user needs, add it as an extra (matching the existing swift/qp/collision pattern) rather than making it a core dependency. Co-Authored-By: Claude Sonnet 5 --- README.md | 11 +++++++++-- docs/source/install.rst | 9 +++++++-- pyproject.toml | 4 ++++ src/roboticstoolbox/bin/rtbtool.py | 16 +++++++++++----- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d32b7ce0..5942553a 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,8 @@ Available options are: - `swift` install [Swift](https://github.com/jhavl/swift), a web-based visualizer - `qp` install quadratic-programming IK dependencies (`qpsolvers`, `quadprog`) - `collision` install collision checking with [coal](https://github.com/coal-library/coal) and `trimesh` -- `all` install `swift`, `qp`, and `collision` +- `tool` install `IPython` and `pygments`, needed to run the `rtbtool` interactive shell +- `all` install `swift`, `qp`, `collision`, and `tool` > **Windows note:** `coal` does not publish Windows wheels on PyPI, so the > `collision`/`all` extras skip it there and collision checking is @@ -155,7 +156,13 @@ pip install roboticstoolbox-python[qp] pip install roboticstoolbox-python[collision] ``` -- Everything (swift + qp + collision) +- `rtbtool` interactive shell dependencies only + +```shell script +pip install roboticstoolbox-python[tool] +``` + +- Everything (swift + qp + collision + tool) ```shell script pip install roboticstoolbox-python[all] diff --git a/docs/source/install.rst b/docs/source/install.rst index af7281b3..66cfd07c 100644 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -16,7 +16,8 @@ Available extras: - ``swift`` install `Swift `_, a web-based visualizer - ``qp`` install quadratic-programming IK dependencies (``qpsolvers``, ``quadprog``) - ``collision`` install collision checking with `coal `_ and ``trimesh`` -- ``all`` install ``swift``, ``qp``, and ``collision`` +- ``tool`` install ``IPython`` and ``pygments``, needed to run the ``rtbtool`` interactive shell +- ``all`` install ``swift``, ``qp``, ``collision``, and ``tool`` .. warning:: ``coal`` does not publish Windows wheels on PyPI, so the ``collision``/``all`` extras skip it on Windows and collision checking @@ -46,7 +47,11 @@ Install matrix: pip install roboticstoolbox-python[collision] -- Everything (swift + qp + collision):: +- ``rtbtool`` interactive shell dependencies only:: + + pip install roboticstoolbox-python[tool] + +- Everything (swift + qp + collision + tool):: pip install roboticstoolbox-python[all] diff --git a/pyproject.toml b/pyproject.toml index cc43f47f..5dc00c18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,6 +76,8 @@ collision = ["coal; sys_platform != 'win32'", "trimesh"] qp = ["qpsolvers", "quadprog"] +tool = ["ipython", "pygments"] + all = [ "swift-sim>=1.0.0", "websockets", @@ -83,6 +85,8 @@ all = [ "quadprog", "coal; sys_platform != 'win32'", "trimesh", + "ipython", + "pygments", ] dev = [ diff --git a/src/roboticstoolbox/bin/rtbtool.py b/src/roboticstoolbox/bin/rtbtool.py index ff4a86c0..993ae541 100755 --- a/src/roboticstoolbox/bin/rtbtool.py +++ b/src/roboticstoolbox/bin/rtbtool.py @@ -10,11 +10,6 @@ """ # import stuff -from pygments.token import Token -from IPython.terminal.prompts import Prompts -from IPython.terminal.prompts import ClassicPrompts -from traitlets.config import Config -import IPython import argparse from pathlib import Path import shlex @@ -221,6 +216,17 @@ def startup(): def main(): + try: + import IPython + from IPython.terminal.prompts import Prompts + from pygments.token import Token + from traitlets.config import Config + except ImportError as e: + sys.exit( + f"rtbtool requires IPython and pygments, which are not " + f"installed ({e}).\nInstall them with:\n\n" + " pip install roboticstoolbox-python[tool]\n" + ) args, ipython_args = parse_arguments()