From 2ec2c4af08612fff4b606ee636602da2f2905a4c Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 05:31:56 +0000 Subject: [PATCH 1/2] fix: handle StopIteration in discovery When no discovery plugins are found, the application would crash with a StopIteration. This change catches the StopIteration and raises a RuntimeError with a more informative message. Fixes #2493 --- docs/changelog/2493.bugfix.rst | 3 +++ src/virtualenv/run/plugin/discovery.py | 7 ++++++- tests/unit/config/test___main__.py | 10 ++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 docs/changelog/2493.bugfix.rst diff --git a/docs/changelog/2493.bugfix.rst b/docs/changelog/2493.bugfix.rst new file mode 100644 index 000000000..7a29f1771 --- /dev/null +++ b/docs/changelog/2493.bugfix.rst @@ -0,0 +1,3 @@ +When no discovery plugins are found, the application would crash with a StopIteration. +This change catches the StopIteration and raises a RuntimeError with a more informative message. +Contributed by :user:`esafak`. \ No newline at end of file diff --git a/src/virtualenv/run/plugin/discovery.py b/src/virtualenv/run/plugin/discovery.py index a963042d0..5e8b2392f 100644 --- a/src/virtualenv/run/plugin/discovery.py +++ b/src/virtualenv/run/plugin/discovery.py @@ -16,10 +16,15 @@ def get_discover(parser, args): choices = _get_default_discovery(discover_types) # prefer the builtin if present, otherwise fallback to first defined type choices = sorted(choices, key=lambda a: 0 if a == "builtin" else 1) + try: + default_discovery = next(iter(choices)) + except StopIteration as e: + msg = "No discovery plugin found. Try reinstalling virtualenv to fix this issue." + raise RuntimeError(msg) from e discovery_parser.add_argument( "--discovery", choices=choices, - default=next(iter(choices)), + default=default_discovery, required=False, help="interpreter discovery method", ) diff --git a/tests/unit/config/test___main__.py b/tests/unit/config/test___main__.py index b7c1850c5..0bd2569d6 100644 --- a/tests/unit/config/test___main__.py +++ b/tests/unit/config/test___main__.py @@ -52,6 +52,16 @@ def test_fail_no_traceback(raise_on_session_done, tmp_path, capsys): assert err == "err\n" +def test_discovery_fails_no_discovery_plugin(mocker, tmp_path, capsys): + mocker.patch("virtualenv.run.plugin.discovery.Discovery.entry_points_for", return_value={}) + with pytest.raises(SystemExit) as context: + run_with_catch([str(tmp_path)]) + assert context.value.code == 1 + out, err = capsys.readouterr() + assert "RuntimeError: No discovery plugin found. Try reinstalling virtualenv to fix this issue." in out + assert not err + + def test_fail_with_traceback(raise_on_session_done, tmp_path, capsys): raise_on_session_done(TypeError("something bad")) From 777a191f9b16a07b533bbf941be7699d6098b286 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 15:01:16 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/changelog/2493.bugfix.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog/2493.bugfix.rst b/docs/changelog/2493.bugfix.rst index 7a29f1771..1ac87c85a 100644 --- a/docs/changelog/2493.bugfix.rst +++ b/docs/changelog/2493.bugfix.rst @@ -1,3 +1,3 @@ When no discovery plugins are found, the application would crash with a StopIteration. This change catches the StopIteration and raises a RuntimeError with a more informative message. -Contributed by :user:`esafak`. \ No newline at end of file +Contributed by :user:`esafak`.