Skip to content

fix: skip plugin loading for --version/-V flag#10781

Open
majiayu000 wants to merge 2 commits intopython-poetry:mainfrom
majiayu000:fix/issue-10625-skip-plugins-for-version
Open

fix: skip plugin loading for --version/-V flag#10781
majiayu000 wants to merge 2 commits intopython-poetry:mainfrom
majiayu000:fix/issue-10625-skip-plugins-for-version

Conversation

@majiayu000
Copy link
Copy Markdown

@majiayu000 majiayu000 commented Mar 24, 2026

Pull Request Check List

Resolves: #10625

  • Added tests for changed code.
  • Updated documentation for changed code.

Summary

poetry --version is slower than necessary because it loads all plugins even though plugins cannot affect version output.

This adds a check for --version/-V in _load_plugins() alongside the existing --no-plugins check. When either flag is present, plugin loading is skipped entirely.

The only_params=True argument matches cleo's own --version detection in BaseApplication._run(), so poetry run -- --version correctly still loads plugins (because --version appears after the -- separator).

Single-line condition change, no new dependencies.

Test Plan

Added parametrized test covering both --version and -V flags, verifying:

  • Exit code 0 with correct version output
  • PluginManager is never instantiated
  • _plugins_loaded flag is still set (prevents re-entry)

Summary by Sourcery

Skip loading plugins when the application is invoked with the --version/-V flags to speed up version output while preserving existing behavior for other commands.

Bug Fixes:

  • Prevent unnecessary plugin initialization when running poetry --version or poetry -V, reducing overhead for version checks.

Tests:

  • Add parametrized tests verifying that version commands skip plugin loading while still returning the correct version and marking plugins as loaded.

Skip loading plugins when --version or -V is passed since plugins
cannot affect version output. This reduces startup time by avoiding
unnecessary plugin initialization.

Signed-off-by: majiayu000 <1835304752@qq.com>
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Mar 24, 2026

Reviewer's Guide

Skips plugin loading when the Poetry application is invoked with top-level version flags (--version / -V) by extending the plugin-loading guard, and adds a parametrized test to verify plugin manager is not instantiated while version output and internal plugin state remain correct.

Sequence diagram for version flag execution and plugin loading

sequenceDiagram
    actor User
    participant Shell
    participant PoetryApplication
    participant IO
    participant Input
    participant PluginManager

    User->>Shell: poetry --version
    Shell->>PoetryApplication: invoke main
    PoetryApplication->>IO: create IO
    IO->>Input: parse argv

    PoetryApplication->>PoetryApplication: _load_plugins(io)
    PoetryApplication->>Input: has_parameter_option("--no-plugins")
    Input-->>PoetryApplication: false
    PoetryApplication->>Input: has_parameter_option(["--version","-V"], only_params=True)
    Input-->>PoetryApplication: true
    PoetryApplication-->>PluginManager: skip instantiation

    PoetryApplication->>PoetryApplication: mark _plugins_loaded = True
    PoetryApplication->>PoetryApplication: resolve version
    PoetryApplication-->>IO: write version to output
    IO-->>User: display version
    PoetryApplication-->>Shell: exit code 0
Loading

Class diagram for updated plugin loading logic in application

classDiagram
    class PoetryApplication {
        bool _disable_plugins
        bool _plugins_loaded
        _load_plugins(io: IO) void
    }

    class IO {
        Input input
    }

    class Input {
        has_parameter_option(values, only_params) bool
    }

    class PluginManager {
        PluginManager() void
        load_plugins() void
    }

    class ApplicationPlugin {
        name str
        activate() void
    }

    PoetryApplication --> IO : uses
    IO --> Input : wraps
    PoetryApplication ..> PluginManager : conditionally_instantiates
    PluginManager ..> ApplicationPlugin : manages

    note for PoetryApplication "_load_plugins now skips PluginManager instantiation when --no-plugins is set or when --version/-V are present as top-level options (only_params = True)."
Loading

File-Level Changes

Change Details Files
Guard plugin loading so it is skipped when the CLI is invoked with top-level --version/-V flags, matching cleo’s only_params behavior.
  • Extend the _load_plugins condition to also check for --version and -V flags using io.input.has_parameter_option([...], only_params=True)
  • Ensure plugins are not loaded when version flags are passed before --, but still load for poetry run -- --version
src/poetry/console/application.py
Add regression test ensuring version flags bypass plugin manager instantiation while preserving correct exit code, version output, and internal plugin-loaded state.
  • Introduce parametrized pytest over --version and -V that executes the application with a test plugin installed
  • Mock PluginManager to assert it is never instantiated when using version flags
  • Assert the application exits with status code 0 and _plugins_loaded is set to True after running with version flags
tests/console/test_application.py

Assessment against linked issues

Issue Objective Addressed Explanation
#10625 Avoid loading plugins when running poetry --version or poetry -V so that version checks are as fast as running with --no-plugins.
#10625 Preserve normal plugin behavior for other commands and argument patterns (e.g. poetry run -- --version) while implementing the faster version path.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@majiayu000 majiayu000 marked this pull request as ready for review March 24, 2026 13:20
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The new test reaches into the private _plugins_loaded attribute to assert behavior; consider asserting the externally observable behavior (e.g., no plugin side effects) instead of relying on an internal implementation detail that may change.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new test reaches into the private `_plugins_loaded` attribute to assert behavior; consider asserting the externally observable behavior (e.g., no plugin side effects) instead of relying on an internal implementation detail that may change.

## Individual Comments

### Comment 1
<location path="tests/console/test_application.py" line_range="86-95" />
<code_context>
     assert tester.status_code == 0


+@pytest.mark.parametrize("flag", ["--version", "-V"])
+def test_application_with_plugins_skipped_for_version(
+    flag: str, with_add_command_plugin: None, mocker: MockerFixture
+) -> None:
+    app = Application()
+
+    manager_mock = mocker.patch(
+        "poetry.plugins.plugin_manager.PluginManager", autospec=True
+    )
+
+    tester = ApplicationTester(app)
+    tester.execute(flag)
+
+    assert tester.status_code == 0
+    assert app._plugins_loaded is True
+    manager_mock.assert_not_called()
+
</code_context>
<issue_to_address>
**suggestion (testing):** Add an assertion that the version output is correct, not just that the exit code is 0

Since this test is meant to validate the version behavior, it should also assert the actual output, not just success and plugin behavior. Please add a check that `tester.io.fetch_output()` (or similar) includes the expected version string (e.g. `__version__` or `app.get_version()`), so changes to the version output are caught by this test.

Suggested implementation:

```python
@pytest.mark.parametrize("flag", ["--version", "-V"])
def test_application_with_plugins_skipped_for_version(
    flag: str, with_add_command_plugin: None, mocker: MockerFixture
) -> None:
    app = Application()

    manager_mock = mocker.patch(
        "poetry.plugins.plugin_manager.PluginManager", autospec=True
    )

    tester = ApplicationTester(app)
    tester.execute(flag)

    output = tester.io.fetch_output()

    assert tester.status_code == 0
    assert app._plugins_loaded is True
    manager_mock.assert_not_called()
    assert __version__ in output

```

To make this compile, ensure this test module imports `__version__` from Poetry's version module near the top of the file, for example:

`from poetry.__version__ import __version__`

If a different version symbol or helper (e.g. `Application().version` or `Application().get_version()`) is already used elsewhere in the tests, adjust the assertion to check for that value instead of `__version__`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +86 to +95
@pytest.mark.parametrize("flag", ["--version", "-V"])
def test_application_with_plugins_skipped_for_version(
flag: str, with_add_command_plugin: None, mocker: MockerFixture
) -> None:
app = Application()

manager_mock = mocker.patch(
"poetry.plugins.plugin_manager.PluginManager", autospec=True
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Add an assertion that the version output is correct, not just that the exit code is 0

Since this test is meant to validate the version behavior, it should also assert the actual output, not just success and plugin behavior. Please add a check that tester.io.fetch_output() (or similar) includes the expected version string (e.g. __version__ or app.get_version()), so changes to the version output are caught by this test.

Suggested implementation:

@pytest.mark.parametrize("flag", ["--version", "-V"])
def test_application_with_plugins_skipped_for_version(
    flag: str, with_add_command_plugin: None, mocker: MockerFixture
) -> None:
    app = Application()

    manager_mock = mocker.patch(
        "poetry.plugins.plugin_manager.PluginManager", autospec=True
    )

    tester = ApplicationTester(app)
    tester.execute(flag)

    output = tester.io.fetch_output()

    assert tester.status_code == 0
    assert app._plugins_loaded is True
    manager_mock.assert_not_called()
    assert __version__ in output

To make this compile, ensure this test module imports __version__ from Poetry's version module near the top of the file, for example:

from poetry.__version__ import __version__

If a different version symbol or helper (e.g. Application().version or Application().get_version()) is already used elsewhere in the tests, adjust the assertion to check for that value instead of __version__.

@dosubot
Copy link
Copy Markdown

dosubot Bot commented Mar 24, 2026

Related Documentation

2 document(s) may need updating based on files changed in this PR:

Python Poetry

cli /poetry/blob/main/docs/cli.md
View Suggested Changes
@@ -40,7 +40,7 @@
 * `--quiet (-q)` : Do not output any message.
 * `--ansi`: Force ANSI output.
 * `--no-ansi`: Disable ANSI output.
-* `--version (-V)`: Display this application version.
+* `--version (-V)`: Display this application version. Plugins are not loaded when using this flag for performance reasons.
 * `--no-interaction (-n)`: Do not ask any interactive question.
 * `--no-plugins`: Disables plugins.
 * `--no-cache`: Disables Poetry source caches.

[Accept] [Decline]

plugins /poetry/blob/main/docs/plugins.md
View Suggested Changes
@@ -189,6 +189,12 @@
 
 Installed plugin packages are automatically loaded when Poetry starts up.
 
+{{% note %}}
+Plugins are not loaded when using the `--version` (or `-V`) flag.
+This improves performance for version checks, but also means plugins cannot affect the version output.
+Plugins are also not loaded when the `--no-plugins` flag is used.
+{{% /note %}}
+
 You have multiple ways to install plugins for Poetry
 
 ### With `pipx inject`

[Accept] [Decline]

Note: You must be authenticated to accept/decline updates.

How did I do? Any feedback?  Join Discord

Replace _plugins_loaded assertion with version output check to avoid
relying on internal implementation details.

Signed-off-by: majiayu000 <1835304752@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

poetry --version is slower than it could be

1 participant