Skip to content

fix: suggest poetry self lock for self commands (#10536)#10723

Closed
veeceey wants to merge 1 commit intopython-poetry:mainfrom
veeceey:fix/issue-10536
Closed

fix: suggest poetry self lock for self commands (#10536)#10723
veeceey wants to merge 1 commit intopython-poetry:mainfrom
veeceey:fix/issue-10536

Conversation

@veeceey
Copy link

@veeceey veeceey commented Feb 8, 2026

Summary

  • When poetry self subcommands (e.g. self install, self sync, self show) encounter an outdated or missing lock file, the error message now correctly suggests poetry self lock instead of poetry lock
  • Added set_lock_command_hint() method to Installer to allow customizing the lock command suggestion in error messages
  • Added _lock_command_hint property to ShowCommand (overridden in SelfShowCommand) for the "lock not found" error message

Fixes #10536

Test plan

  • Existing test_not_fresh_lock test continues to verify the default poetry lock suggestion
  • New test_not_fresh_lock_custom_hint test verifies the poetry self lock suggestion when the hint is set
  • New test_show_errors_without_lock_file_suggests_self_lock test verifies poetry self show suggests poetry self lock
  • All existing self command tests pass (31 passed, 1 skipped)
  • All existing show and check command lock-related tests pass

🤖 Generated with Claude Code

Summary by Sourcery

Update lock-file related error hints so self subcommands correctly reference poetry self lock and make the installer’s lock hint configurable.

Bug Fixes:

  • Correct self command error messages to suggest poetry self lock when the self lock file is missing or outdated.

Enhancements:

  • Add configurable lock command hint to the installer and show command so different command contexts can customize lock-related guidance.

Tests:

  • Extend installer and self show tests to cover custom lock command hints and the new poetry self lock suggestion for self commands.

…mands

When `poetry self` subcommands encounter an outdated or missing lock file,
the error message now correctly suggests `poetry self lock` instead of
`poetry lock`, which would operate on the wrong pyproject.toml.

Fixes python-poetry#10536

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sourcery-ai
Copy link

sourcery-ai bot commented Feb 8, 2026

Reviewer's Guide

Makes lock-file related error messages configurable so that self-related commands suggest poetry self lock instead of poetry lock, and wires this through installer and show commands with corresponding tests.

Sequence diagram for poetry self install with custom lock command hint

sequenceDiagram
    actor User
    participant Cli as PoetryCli
    participant SelfCmd as SelfCommand
    participant Inst as Installer
    participant Lock as Locker

    User->>Cli: run "poetry self install"
    Cli->>SelfCmd: handle()
    SelfCmd->>SelfCmd: reset()
    SelfCmd->>Inst: set_lock_command_hint("poetry self lock")
    SelfCmd->>Inst: run()
    Inst->>Lock: is_locked()
    alt lock file present
        Inst->>Lock: is_fresh()
        alt lock not fresh
            Inst-->>User: error pyproject changed. Run "poetry self lock" to fix the lock file.
        else lock fresh
            Inst-->>User: perform installation
        end
    else lock file missing
        Inst-->>User: error poetry.lock not found. Run "poetry self lock" to create it.
    end
Loading

Sequence diagram for poetry self show using overridden lock command hint

sequenceDiagram
    actor User
    participant Cli as PoetryCli
    participant SelfShow as SelfShowCommand
    participant Locker as Locker

    User->>Cli: run "poetry self show"
    Cli->>SelfShow: handle()
    SelfShow->>Locker: is_locked()
    alt lock file missing
        SelfShow-->>User: Error: poetry.lock not found. Run "poetry self lock" to create it.
    else lock file present
        SelfShow-->>User: show package information
    end
Loading

Class diagram for configurable lock command hints in installer and show commands

classDiagram
    class Installer {
        -Locker _locker
        -bool _update
        -Iterable~NormalizedName~ _groups
        -bool _skip_directory
        -bool _lock
        -str _lock_command_hint
        -list~NormalizedName~ _whitelist
        +__init__(io, env, package, locker, pool, config, installed_repository, execute_operations)
        +set_locker(locker Locker) Installer
        +set_lock_command_hint(hint str) Installer
        +run() int
        -_do_install() int
    }

    class Locker {
        +is_locked() bool
        +is_fresh() bool
        +is_locked_groups_and_markers() bool
    }

    class ShowCommand {
        <<abstract>>
        +name str
        +description str
        +arguments list~Argument~
        +handle() int
        +activated_groups() set~NormalizedName~
        +_lock_command_hint str
    }

    class SelfCommand {
        +installer Installer
        +system_pyproject
        +handle() int
        +reset() None
        -_system_project_handle() int
    }

    class SelfShowCommand {
        +description str
        +_lock_command_hint str
        +activated_groups() set~NormalizedName~
    }

    Installer --> Locker : uses
    SelfCommand --> Installer : configures
    SelfShowCommand --|> ShowCommand
    SelfShowCommand --|> SelfCommand

    ShowCommand : _lock_command_hint = "poetry lock"
    SelfShowCommand : _lock_command_hint = "poetry self lock"
    Installer : _lock_command_hint = "poetry lock"
    Installer : set_lock_command_hint sets _lock_command_hint
    SelfCommand : handle calls installer.set_lock_command_hint("poetry self lock")
Loading

File-Level Changes

Change Details Files
Make installer lock-file hint configurable and default to poetry lock.
  • Add _lock_command_hint attribute to Installer with default value "poetry lock"
  • Introduce set_lock_command_hint() on Installer to override the suggested lock command
  • Use _lock_command_hint when raising the stale-lock ValueError in _do_install
src/poetry/installation/installer.py
tests/installation/test_installer.py
Make show command use a configurable lock command hint, with self show overriding it to poetry self lock.
  • Add _lock_command_hint property on ShowCommand returning "poetry lock"
  • Use _lock_command_hint in the missing-lock error message in ShowCommand.handle
  • Override _lock_command_hint in SelfShowCommand to return "poetry self lock"
  • Set installer lock hint to "poetry self lock" in SelfCommand.handle so self installs use the correct suggestion
src/poetry/console/commands/show.py
src/poetry/console/commands/self/show/__init__.py
src/poetry/console/commands/self/self_command.py
Add tests ensuring custom lock hints and self show behavior are correct.
  • Extend installer tests with test_not_fresh_lock_custom_hint to verify custom lock hint appears in stale-lock error
  • Extend self show tests with test_show_errors_without_lock_file_suggests_self_lock to verify missing-lock error suggests poetry self lock
tests/installation/test_installer.py
tests/console/commands/self/test_show.py

Assessment against linked issues

Issue Objective Addressed Explanation
#10536 For regular (non-self) Poetry commands, keep the existing behavior where outdated or missing lock files suggest running poetry lock.
#10536 For poetry self subcommands that rely on the Poetry installation’s lock file, update error messages so that outdated or missing lock files suggest running poetry self lock instead of poetry lock.

Possibly linked issues


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

Copy link

@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

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `tests/console/commands/self/test_show.py:79-83` </location>
<code_context>
     assert tester.io.fetch_output().strip() == expected
+
+
+def test_show_errors_without_lock_file_suggests_self_lock(
+    tester: CommandTester,
+) -> None:
+    command = tester.command
+    assert isinstance(command, SelfCommand)
+    # Ensure the system pyproject exists but the lock file doesn't
+    system_pyproject_file = command.system_pyproject
+    system_pyproject_file.parent.mkdir(parents=True, exist_ok=True)
+    lock_path = system_pyproject_file.parent.joinpath("poetry.lock")
+    if lock_path.exists():
+        lock_path.unlink()
+
+    tester.execute()
+
+    expected = "Error: poetry.lock not found. Run `poetry self lock` to create it.\n"
+    assert tester.io.fetch_error() == expected
+    assert tester.status_code == 1
</code_context>

<issue_to_address>
**suggestion (testing):** Clarify or align the comment about ensuring the system pyproject exists

The inline comment claims the system pyproject exists, but this test only creates the parent directory and never the `system_pyproject_file` itself. That makes the test misleading and potentially brittle if later code checks for the file’s existence. Either create a minimal `system_pyproject_file` here so behavior matches the comment, or reword the comment to reflect that only the directory (and absence of `poetry.lock`) is being ensured.

```suggestion
    assert isinstance(command, SelfCommand)
    # Ensure the system pyproject exists but the lock file doesn't
    system_pyproject_file = command.system_pyproject
    system_pyproject_file.parent.mkdir(parents=True, exist_ok=True)
    # Create a minimal system pyproject file so the test setup matches the comment
    system_pyproject_file.write_text("")
    lock_path = system_pyproject_file.parent.joinpath("poetry.lock")
```
</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 +79 to +83
assert isinstance(command, SelfCommand)
# Ensure the system pyproject exists but the lock file doesn't
system_pyproject_file = command.system_pyproject
system_pyproject_file.parent.mkdir(parents=True, exist_ok=True)
lock_path = system_pyproject_file.parent.joinpath("poetry.lock")
Copy link

Choose a reason for hiding this comment

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

suggestion (testing): Clarify or align the comment about ensuring the system pyproject exists

The inline comment claims the system pyproject exists, but this test only creates the parent directory and never the system_pyproject_file itself. That makes the test misleading and potentially brittle if later code checks for the file’s existence. Either create a minimal system_pyproject_file here so behavior matches the comment, or reword the comment to reflect that only the directory (and absence of poetry.lock) is being ensured.

Suggested change
assert isinstance(command, SelfCommand)
# Ensure the system pyproject exists but the lock file doesn't
system_pyproject_file = command.system_pyproject
system_pyproject_file.parent.mkdir(parents=True, exist_ok=True)
lock_path = system_pyproject_file.parent.joinpath("poetry.lock")
assert isinstance(command, SelfCommand)
# Ensure the system pyproject exists but the lock file doesn't
system_pyproject_file = command.system_pyproject
system_pyproject_file.parent.mkdir(parents=True, exist_ok=True)
# Create a minimal system pyproject file so the test setup matches the comment
system_pyproject_file.write_text("")
lock_path = system_pyproject_file.parent.joinpath("poetry.lock")

@dimbleby
Copy link
Contributor

dimbleby commented Feb 9, 2026

Cf #10715

You've made at least a couple of pull requests that duplicate existing PRs. You probably should say what it is you think un-fixable about the originals.

@veeceey
Copy link
Author

veeceey commented Feb 9, 2026

Thanks for pointing this out @dimbleby — you're right, this duplicates #10715. I should have checked for existing PRs before opening this. Closing in favor of #10715 which addresses the same issue. Apologies for the noise.

@veeceey veeceey closed this Feb 9, 2026
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.

Clarify "poetry lock" suggestion provided for poetry self subcommands

2 participants