Skip to content

Conversation

@ghost
Copy link

@ghost ghost commented Apr 12, 2025

Implement the poetry wrapper command to generate a poetryw Bash script and poetry-wrapper.properties file, enabling version-pinned Poetry usage on Linux and macOS. The generated script ensures consistent Poetry versions across environments without requiring global installation, streamlining development and CI/CD workflows.

Features:

  • Generates a Bash script (poetryw) that installs and runs a specified Poetry version.
  • Supports custom versions via --poetry-version (e.g., 2.1.2).
  • Validates semantic version format (X.Y.Z).
  • Overwrites existing files with a warning.
  • Sets executable permissions on POSIX systems.

Limitations:

  • Only supports Linux and macOS (Windows requires additional work).
  • Does not verify Poetry installer integrity (e.g., checksums).

Tests cover version validation, script generation, file permissions, and error cases (invalid versions, file write failures).

Summary by Sourcery

Implement a new poetry wrapper command to generate a version-pinned Poetry execution script for Unix-like systems

New Features:

  • Add a new CLI command that generates a poetryw script to ensure consistent Poetry version usage across environments
  • Create a mechanism to install and run a specific Poetry version locally without global installation

Documentation:

  • Add documentation for the new wrapper command in CLI documentation, explaining usage, generated files, and system limitations

Tests:

  • Implement comprehensive test suite covering version validation, script generation, file permissions, and error handling for the wrapper command

@sourcery-ai
Copy link

sourcery-ai bot commented Apr 12, 2025

Reviewer's Guide by Sourcery

This pull request introduces a poetry wrapper command that generates a poetryw script and poetry-wrapper.properties file to pin a specific Poetry version for a project. It includes version validation, automatic installation of the specified Poetry version, documentation updates, and a comprehensive test suite.

Sequence diagram for generating the poetry wrapper

sequenceDiagram
    participant User
    participant PoetryCLI
    participant WrapperCommand
    participant FileSystem

    User->>PoetryCLI: poetry wrapper --poetry-version=2.1.2
    PoetryCLI->>WrapperCommand: handle()
    WrapperCommand->>WrapperCommand: _is_valid_version("2.1.2")
    alt Version is valid
        WrapperCommand->>FileSystem: Check if poetryw and poetry-wrapper.properties exist
        alt Files exist
            WrapperCommand->>PoetryCLI: Output warning about overwriting files
        end
        WrapperCommand->>FileSystem: Write poetry-wrapper.properties with version=2.1.2
        WrapperCommand->>WrapperCommand: _generate_script_content("2.1.2")
        WrapperCommand->>FileSystem: Write poetryw script
        WrapperCommand->>WrapperCommand: _make_executable(poetryw)
        WrapperCommand->>PoetryCLI: Output success message and file locations
    else Version is invalid
        WrapperCommand->>PoetryCLI: Output error message
    end
Loading

Sequence diagram for executing the poetryw script

sequenceDiagram
    participant User
    participant poetryw
    participant FileSystem
    participant Poetry

    User->>poetryw: ./poetryw install
    poetryw->>FileSystem: Check if poetry-wrapper.properties exists
    alt File exists
        poetryw->>FileSystem: Read version from poetry-wrapper.properties
        poetryw->>poetryw: Set POETRY_HOME to version-specific cache
        poetryw->>FileSystem: Check if Poetry is installed in POETRY_HOME
        alt Poetry is not installed
            poetryw->>poetryw: Install Poetry version from install.python-poetry.org
        end
        poetryw->>Poetry: Execute Poetry with provided arguments (install)
        Poetry-->>User: Output from Poetry
    else File does not exist
        poetryw->>User: Output error message
    end
Loading

File-Level Changes

Change Details Files
Implemented a new wrapper command to generate a poetryw Bash script and a poetry-wrapper.properties file for pinning Poetry versions.
  • Added a wrapper command to the application.
  • Created a poetryw Bash script to execute Poetry commands with a specific version.
  • Generated a poetry-wrapper.properties file to store the pinned Poetry version.
  • Added options to specify a custom Poetry version via --poetry-version.
src/poetry/console/application.py
src/poetry/console/commands/wrapper.py
Added validation for semantic version format (X.Y.Z) for the Poetry version.
  • Implemented version validation to ensure the specified version adheres to the X.Y.Z format.
  • Provided error messages for invalid version formats.
src/poetry/console/commands/wrapper.py
tests/console/commands/test_wrapper.py
Enhanced the command to automatically install the specified Poetry version if it's not already present.
  • Added logic to check if the specified Poetry version is installed.
  • Implemented installation of the specified Poetry version if it's missing.
  • Set the POETRY_HOME environment variable to a version-specific cache directory.
src/poetry/console/commands/wrapper.py
Updated documentation to include the new wrapper command and its usage.
  • Added documentation for the wrapper command.
  • Included usage examples and notes about platform support.
  • Documented the generated files (poetryw and poetry-wrapper.properties).
docs/cli.md
Added a comprehensive test suite for the wrapper command.
  • Added tests for version validation.
  • Added tests for script generation.
  • Added tests for file permission handling.
  • Added tests for error scenarios (invalid versions, file write failures).
tests/console/commands/test_wrapper.py

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!
  • Generate a plan of action for an issue: Comment @sourcery-ai plan on
    an issue to generate a plan of action for it.

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 @ranzyblessings - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider adding a check for the existence of the poetry executable after installation in the generated script.
  • The documentation update includes some unnecessary whitespace changes; consider reverting those.
Here's what I looked at during the review
  • 🟡 General issues: 1 issue found
  • 🟡 Security: 1 issue found
  • 🟡 Testing: 3 issues found
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

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.

@ghost
Copy link
Author

ghost commented Apr 12, 2025

Add poetry wrapper Command for Version-Pinned Execution

Overview

This pull request introduces the poetry wrapper command, which generates a poetryw Bash script and a poetry-wrapper.properties file to pin a specific Poetry version for project-local execution. Implemented for Linux and macOS, this feature ensures consistent Poetry versions across development, CI/CD, and production environments without requiring a global Poetry installation.

Changes Implemented

  • New Command: Added poetry wrapper to generate:
    • poetryw: A Bash script that installs and executes a specified Poetry version.
    • poetry-wrapper.properties: Stores the pinned version (e.g., version=2.1.2).
  • Features:
    • Supports the current Poetry version by default or a custom version via --poetry-version (e.g., poetry wrapper --poetry-version 2.1.2).
    • Validates version format (X.Y.Z) using regex.
    • Warns and overwrites existing poetryw or poetry-wrapper.properties files.
    • Sets executable permissions on POSIX systems.
    • Includes detailed help text (poetry wrapper --help) with usage examples.
  • Script Behavior:
    • Checks for poetry-wrapper.properties at runtime.
    • Installs the specified Poetry version to ~/.poetry/versions/<version> if missing.
    • Executes Poetry with provided arguments (exec ... "$@").
  • Testing:
    • Comprehensive unit tests cover version validation, script generation, file permissions, default/custom version handling, and error cases (invalid versions, file write failures).
    • Uses pytest fixtures and mocks for deterministic testing.

Feature Enhancements

  • Reproducibility: Ensures environment parity by locking the Poetry version, reducing setup errors and CI/CD variability.
  • Developer Experience: Simplifies onboarding for engineers familiar with wrapper-based tools (e.g., gradlew, mvnw).
  • Flexibility: Supports custom versions, making it adaptable to legacy or specific project requirements.
  • Error Handling: Gracefully handles file I/O errors, invalid inputs, and existing files with clear user feedback.

Limitations

  • Platform Support: Currently implemented for Linux and macOS only. Windows support requires generating a .bat or .ps1 script and handling non-POSIX permissions, which is planned for a future iteration.
  • Installer Verification: Does not verify the Poetry installer’s integrity (e.g., via checksums). This is a potential security enhancement for production use.
  • Version Availability: Does not validate whether the specified version exists in a registry (e.g., PyPI), which could lead to runtime errors for invalid versions.

Testing Instructions

To test this feature locally, follow these steps:

  1. Set Up Poetry Environment:

    poetry install
    poetry env info --path  # Verify the environment
    source <path-to-virtualenv>/bin/activate  # e.g., /home/user/.cache/pypoetry/virtualenvs/poetry-Fs4_m_BR-py3.12/bin/activate
  2. Run Commands

    poetry wrapper --help  # View command usage
    poetry wrapper  # Generate poetryw and poetry-wrapper.properties with current version
    poetry wrapper --poetry-version 2.1.2  # Generate with a custom version
  3. Verify Output

  • Check that poetryw and poetry-wrapper.properties are created in the current directory.
  • Inspect poetry-wrapper.properties for the correct version (e.g., version=2.1.2).
  • Run ./poetryw --version to confirm it executes the pinned Poetry version.

Impact

This feature aligns Poetry with modern build ecosystems (e.g., Gradle, Maven) by providing a wrapper-based workflow. It reduces onboarding friction, eliminates version drift, and streamlines CI/CD pipelines, making Poetry more accessible to both Python and non-Python engineers.

Future Work

  • Add Windows support with a .bat or .ps1 wrapper script.
  • Implement installer checksum verification for enhanced security.
  • Add an option to validate version availability against a registry.
  • Support custom output paths or script names for advanced use cases.

Acknowledgments

Inspired by tools like gradlew and mvnw, this implementation adapts their proven wrapper pattern to Python’s ecosystem, closing a gap in Poetry’s support for reproducible builds.

Please review and provide feedback. I’m happy to address any concerns or iterate on the implementation.

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 @ranzyblessings - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider adding a more robust version validation using packaging.version.parse from the packaging library.
  • The generated script does not handle spaces in the project path; consider quoting the path to $POETRY_HOME.
Here's what I looked at during the review
  • 🟢 General issues: all looks good
  • 🟢 Security: all looks good
  • 🟡 Testing: 1 issue found
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

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.

Ranzy Blessings added 9 commits April 21, 2025 21:15
Implement the `poetry wrapper` command to generate a `poetryw` Bash
script and `poetry-wrapper.properties` file, enabling version-pinned
Poetry usage on Linux and macOS. The generated script ensures consistent
Poetry versions across environments without requiring global installation,
streamlining development and CI/CD workflows.

Features:
- Generates a Bash script (`poetryw`) that installs and runs a specified
  Poetry version.
- Supports custom versions via `--poetry-version` (e.g., `2.1.2`).
- Validates semantic version format (X.Y.Z).
- Overwrites existing files with a warning.
- Sets executable permissions on POSIX systems.

Limitations:
- Only supports Linux and macOS (Windows requires additional work).
- Does not verify Poetry installer integrity (e.g., checksums).

Tests cover version validation, script generation, file permissions,
and error cases (invalid versions, file write failures).

Signed-off-by: Ranzy Blessings <[email protected]>
Document the `poetry wrapper` command in `docs/cli.md` to provide clear usage instructions and reference material for pinning Poetry versions. The documentation details the command’s purpose, options, generated files, and platform-specific notes, ensuring developers can effectively leverage the wrapper for consistent project environments.

Features:
- Describes generating `poetryw` script and `poetry-wrapper.properties` file.
- Includes usage syntax, `--poetry-version` option, and practical examples.
- Clarifies Unix-only support and overwrite behavior.
- Notes version format validation (X.Y.Z) without registry checks.

Formatted to align with Poetry’s `cli.md` style, maintaining consistency with existing command documentation for seamless integration.

Signed-off-by: Ranzy Blessings <[email protected]>
- Added post-installation check for poetry executable in wrapper script
- Simplified chmod permissions to 0o755 for better security
- Removed unnecessary whitespace changes in docs/cli.md
- Added tests for invalid version edge cases and script write errors
- Updated wrapper script tests to verify new installation checks

Signed-off-by: Ranzy Blessings <[email protected]>
…ed on Sourcery-AI Suggestions

- Refactored `WrapperCommand` class to properly annotate mutable class attributes with `ClassVar` to adhere to type-checking guidelines.
- Enhanced wrapper script to validate version format more robustly with basic semantic checks (X.Y.Z format).
- Updated tests to replace nested `with` statements with combined contexts for cleaner code and better readability.
- Fixed missing newline at end of `cli.md` to align with documentation standards.

Signed-off-by: Ranzy Blessings <[email protected]>
- Refactored `test_handle_with_invalid_version` and `test_invalid_version_edge_cases` by combining nested `with` statements into a single `with` block, improving code clarity.
- Streamlined the patching process by merging multiple `patch` calls into one, reducing redundancy and enhancing maintainability.
- This change enhances code readability and aligns with best practices for cleaner, more efficient test code.

*Suggested by Sourcery AI for readability and performance improvements.*

Signed-off-by: Ranzy Blessings <[email protected]>
…lity

- Combined nested `with` statements into a single `with` block in `test_handle_properties_file_write_error` to address Ruff SIM117 warning.
- Improved code clarity and efficiency by streamlining patching process.
- Aligned with Ruff formatting standards to ensure consistency.

*Suggested by Sourcery AI for readability and performance improvements.*

Signed-off-by: Ranzy Blessings <[email protected]>
…able

- Refactored `_make_executable` in `WrapperCommand` to check `os.name` before attempting `chmod`, ensuring consistent behavior on non-POSIX systems like Windows by emitting a warning without relying on `OSError`.
- Added `test_make_executable_on_non_posix` to verify that `_make_executable` on non-POSIX systems outputs the expected warning and preserves file read/write permissions, enhancing test coverage.
- Simplified error handling in `_make_executable` for clarity and reliability, aligning with robust platform-agnostic design principles.
- Suggested by Sourcery-AI: Improved code robustness and test reliability for cross-platform support.

Signed-off-by: Ranzy Blessings <[email protected]>
@ghost
Copy link
Author

ghost commented Apr 21, 2025

Hi @python-poetry/triage, just checking in on this PR. I’ve addressed Sourcery AI’s feedback and ensured CI checks pass. Would appreciate any guidance or next steps. Thanks!

@Secrus
Copy link
Member

Secrus commented Apr 21, 2025

This looks more like a plugin candidate, especially since it introduces a lot of new code to maintain (including bash/sh code, which tends to have many quirks). It's more of a puppy, not a cake (see Will's post)

@Secrus Secrus closed this Apr 21, 2025
@ghost
Copy link
Author

ghost commented Apr 22, 2025

Thanks for the feedback, @Secrus. Understood that this might fit better as a plugin. I’ll consider my options given time constraints. Appreciate the review!

@github-actions
Copy link

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 23, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant