Skip to content

Conversation

@radoering
Copy link
Member

@radoering radoering commented Aug 23, 2025

https://github.com/python-poetry/poetry/actions/runs/17171517004/job/48721759731?pr=10514 (failure in tests/utils/test_isolated_build.py::test_isolated_env_install_discards_requirements_not_needed_by_env with Python 3.14rc2) shows that our installer does not handle environments of Python pre-release versions well. A dependency with the marker python_version == "3.14" is not installed because it is translated into a Python constraint >=3.14,<3.15, which does not allow Python 3.14rc2. With this PR the Python constraint is >=3.14.dev0,<3.15.

Downstream tests are fixed in python-poetry/poetry#10515

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

Summary by Sourcery

Improve marker-to-constraint translation to properly support Python pre-release versions by introducing .dev0 bounds and wildcard expansions for partial-precision markers

New Features:

  • Support pre-release Python versions in marker-derived constraints by using .dev0 for lower bounds

Enhancements:

  • Normalize Python version markers to expand ==x and !=x to x.* and append .dev0 to >=x bounds when precision is less than two segments
  • Treat marker-based >= constraints as stable versions in the version parser for correct handling of dev releases

Tests:

  • Add tests for parsing and formatting of .dev0-based version constraints and update existing expectations to match new wildcard and dev0 conventions

@sourcery-ai
Copy link

sourcery-ai bot commented Aug 23, 2025

Reviewer's Guide

Refactor normalization and parsing of Python version markers to handle pre-release versions by appending '.dev0' for '>=' constraints lacking full precision, replacing tilde-based wildcards with '.*', and ensuring marker-based '>=' operations use the stable version. The test suite is updated throughout to align expectations with these behaviors.

Class diagram for updated Python version marker normalization

classDiagram
    class Utils {
        +normalize_python_version_markers()
    }
    class Parser {
        +parse_single_constraint(op, version, is_marker_constraint)
    }
    Utils --> Parser: uses

    %% Highlight changes
    Utils : + Handles '>=X.Y' by appending '.dev0'
    Utils : + Replaces '~X.Y' with 'X.Y.*' for '=='
    Parser : + For marker-based '>=', uses stable version
Loading

File-Level Changes

Change Details Files
Refactor python version marker normalization to better support pre-release constraints
  • Switch wildcard expansion for '==' markers from '~X.Y' to 'X.Y.*'
  • Append '.dev0' to versions for '>=' markers with only major.minor precision
src/poetry/core/packages/utils/utils.py
Ensure marker-based '>=' constraints use the stable version in parsing
  • Detect marker context in parse_single_constraint and set version to its stable form before building the VersionRange
src/poetry/core/constraints/version/parser.py
Update test suite to expect new wildcard and '.dev0' behaviors
  • Add parameterized tests for parsing '.dev0' constraints and special marker cases
  • Replace all '~X.Y' expectations with 'X.Y.*' in test outputs
  • Update expected python_versions to include '.dev0' for minimal '>=' constraints
tests/constraints/version/test_parse_constraint.py
tests/packages/utils/test_utils.py
tests/test_factory.py
tests/packages/test_main.py
tests/packages/test_dependency.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!

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

  • The new .stable conversion in parse_single_constraint only applies to '>=' — consider applying a similar stable adjustment for '<=' or '<' marker constraints to correctly handle upper bounds with pre-releases.
  • It could be useful to add a test for explicit prerelease markers (e.g. '==3.14rc1') to verify whether parse_marker_version_constraint accepts or rejects them as intended.
  • Consider extracting the '.dev0' bump logic into a shared helper to reduce duplication between normalize_python_version_markers and the parser.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The new .stable conversion in parse_single_constraint only applies to '>=' — consider applying a similar stable adjustment for '<=' or '<' marker constraints to correctly handle upper bounds with pre-releases.
- It could be useful to add a test for explicit prerelease markers (e.g. '==3.14rc1') to verify whether parse_marker_version_constraint accepts or rejects them as intended.
- Consider extracting the '.dev0' bump logic into a shared helper to reduce duplication between normalize_python_version_markers and the parser.

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.

@dimbleby
Copy link
Contributor

dimbleby commented Aug 24, 2025

Discussion here

Tldr the spec is unhelpful, insofar as there is a consensus it probably is that poetry's current behaviour is correct - but the change you are making is desirable and the spec ought to be changed

However I see no such change has happened.

@radoering
Copy link
Member Author

Thanks for the link and the summary.

I intended a more subtle change to only derive correct constraints from markers but the poetry-plugin-export failures in python-poetry/poetry#10515 seem to show that this is not possible because it results in inconsistencies. I may try another approach to fix the original issue.

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.

2 participants