From a31655be13d07acb14548e79c618d62d5bf5589c Mon Sep 17 00:00:00 2001 From: Peter Corke Date: Fri, 24 Jul 2026 08:26:42 +1000 Subject: [PATCH] feat(mvtbtool): add 'tool' extra for IPython/pygments, fail with clear message when missing mvtbtool imports IPython, pygments, and traitlets inside main(), but none of the three were declared as a dependency anywhere -- pip install machinevision-toolbox-python followed by running mvtbtool crashed with a raw ModuleNotFoundError unless IPython happened to already be present transitively (e.g. via Jupyter). Same gap as roboticstoolbox-python's rtbtool, fixed there first. Wrap the imports in a try/except that points the user at the new 'tool' extra instead. Added as an extra (matching the existing ros/jupyter/torch pattern) rather than a core dependency, since mvtbtool is an opt-in interactive shell. Co-Authored-By: Claude Sonnet 5 --- docs/source/installation.rst | 3 +++ pyproject.toml | 5 +++++ src/machinevisiontoolbox/bin/mvtbtool.py | 17 ++++++++++++----- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/docs/source/installation.rst b/docs/source/installation.rst index ac4e4311..205a0f96 100644 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -96,6 +96,9 @@ The available extras are: +--------------+-------------------------------------------+ | ``labelme`` | LabelMe JSON annotation reader support | +--------------+-------------------------------------------+ +| ``tool`` | ``IPython`` and ``pygments``, needed to | +| | run the ``mvtbtool`` interactive shell | ++--------------+-------------------------------------------+ | ``all`` | All of the above | +--------------+-------------------------------------------+ diff --git a/pyproject.toml b/pyproject.toml index e1f92f19..c1c4f891 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,11 +65,14 @@ dependencies = [ # open3d - open3d support (open3d generally won't work with latest Python) # all - all runtime optional features below # ocr - OCR support via pytesseract +# tool - dependencies for the mvtbtool interactive shell dev = ["pytest", "coverage", "ruff", "nbmake"] ros = ["rosbags", "roslibpy", "websockets"] +tool = ["ipython", "pygments"] + docs = [ "sphinx", "pydata-sphinx-theme", @@ -98,6 +101,8 @@ all = [ "rosbags", "roslibpy", "websockets", + "ipython", + "pygments", ] [tool.pytest.ini_options] diff --git a/src/machinevisiontoolbox/bin/mvtbtool.py b/src/machinevisiontoolbox/bin/mvtbtool.py index 5b14076f..437fd2da 100755 --- a/src/machinevisiontoolbox/bin/mvtbtool.py +++ b/src/machinevisiontoolbox/bin/mvtbtool.py @@ -261,6 +261,18 @@ def make_banner(args, optional_modules=None): 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"mvtbtool requires IPython and pygments, which are not " + f"installed ({e}).\nInstall them with:\n\n" + " pip install machinevision-toolbox-python[tool]\n" + ) + args, ipython_args = parse_arguments() torch_modules, torch_warnings = optional_torch_imports(args.torch) @@ -281,11 +293,6 @@ def main(): # exec(path.read_text()) ## drop into IPython - import IPython - from IPython.terminal.prompts import ClassicPrompts, Prompts - from pygments.token import Token - from traitlets.config import Config - class MyPrompt(Prompts): def in_prompt_tokens(self, cli=None): return [(Token.Prompt, args.prompt)]