Skip to content

Comments

Warn users on ~= python version specifier#14008

Merged
zanieb merged 3 commits intoastral-sh:mainfrom
aaron-ang:compat-version
Jun 27, 2025
Merged

Warn users on ~= python version specifier#14008
zanieb merged 3 commits intoastral-sh:mainfrom
aaron-ang:compat-version

Conversation

@aaron-ang
Copy link
Contributor

@aaron-ang aaron-ang commented Jun 12, 2025

Close #7426

Summary

Picking up on #8284, I noticed that the requires_python object already has its specifiers canonicalized in the intersection method, meaning ~=3.12 is converted to >=3.12, <4. To fix this, we check and warn in intersection.

Test Plan

Used the same tests from #8284.

@aaron-ang aaron-ang marked this pull request as ready for review June 13, 2025 01:11
----- stdout -----

----- stderr -----
warning: The release specifier (`~=3.12`) contains a compatible release match without a patch version. This will be interpreted as `>=3.12, <4`. Did you mean `~=3.12.[X]` to freeze the minor version?
Copy link
Contributor Author

@aaron-ang aaron-ang Jun 13, 2025

Choose a reason for hiding this comment

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

How do I hardcode 0 as the patch version? The test converts the patch version to [X], for example ~=3.12.0 to ~=3.12.[X].

Copy link
Member

Choose a reason for hiding this comment

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

The test suite is agnostic to patch versions by default, to allow testing against a wider range of versions downstream.

Do you need the patch version to be represented in this snapshot?

Copy link
Member

@zanieb zanieb Jun 13, 2025

Choose a reason for hiding this comment

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

I see, you want the literal .0 to show. There are a couple things

  1. We should consider updating

    if version.patch().is_none() {
    filters.push((
    format!(r"({})\.\d+", regex::escape(version.to_string().as_str())),
    "$1.[X]".to_string(),
    ));
    }
    to only filter the actual patch version used in the test, rather than an arbitrary \d — that seems separate from this change.

  2. You can select a specific patch version from https://github.com/astral-sh/uv/blob/56ce40b0f4139539f345987f7d5bf88236ae2909/.python-versions then request it in test context construction and add the #[cfg(feature = "python-patch")] feature to the test

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I couldn't figure out a straightforward way to get the patch version in crates/uv/tests/it/common/mod.rs, so I went with the second option.

@zanieb zanieb added the error messages Messaging when something goes wrong label Jun 13, 2025
@aaron-ang
Copy link
Contributor Author

rebased with main

@aaron-ang aaron-ang requested a review from zanieb June 13, 2025 23:22
@aaron-ang
Copy link
Contributor Author

hi @zanieb, any updates on this?

@zanieb
Copy link
Member

zanieb commented Jun 27, 2025

Thanks for you patience :)

@zanieb zanieb merged commit eab938b into astral-sh:main Jun 27, 2025
110 checks passed
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jun 29, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [astral-sh/uv](https://github.com/astral-sh/uv) | patch | `0.7.14` -> `0.7.16` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>astral-sh/uv (astral-sh/uv)</summary>

### [`v0.7.16`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0716)

[Compare Source](astral-sh/uv@0.7.15...0.7.16)

##### Python

- Add Python 3.14.0b3

See the
[`python-build-standalone` release notes](https://github.com/astral-sh/python-build-standalone/releases/tag/20250626)
for more details.

##### Enhancements

- Include path or URL when failing to convert in lockfile ([#&#8203;14292](astral-sh/uv#14292))
- Warn when `~=` is used as a Python version specifier without a patch version ([#&#8203;14008](astral-sh/uv#14008))

##### Preview features

- Ensure preview default Python installs are upgradeable ([#&#8203;14261](astral-sh/uv#14261))

##### Performance

- Share workspace cache between lock and sync operations ([#&#8203;14321](astral-sh/uv#14321))

##### Bug fixes

- Allow local indexes to reference remote files ([#&#8203;14294](astral-sh/uv#14294))
- Avoid rendering desugared prefix matches in error messages ([#&#8203;14195](astral-sh/uv#14195))
- Avoid using path URL for workspace Git dependencies in `requirements.txt` ([#&#8203;14288](astral-sh/uv#14288))
- Normalize index URLs to remove trailing slash ([#&#8203;14245](astral-sh/uv#14245))
- Respect URL-encoded credentials in redirect location ([#&#8203;14315](astral-sh/uv#14315))
- Lock the source tree when running setuptools, to protect concurrent builds ([#&#8203;14174](astral-sh/uv#14174))

##### Documentation

- Note that GCP Artifact Registry download URLs must have `/simple` component ([#&#8203;14251](astral-sh/uv#14251))

### [`v0.7.15`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0715)

[Compare Source](astral-sh/uv@0.7.14...0.7.15)

##### Enhancements

- Consistently use `Ordering::Relaxed` for standalone atomic use cases ([#&#8203;14190](astral-sh/uv#14190))
- Warn on ambiguous relative paths for `--index` ([#&#8203;14152](astral-sh/uv#14152))
- Skip GitHub fast path when rate-limited ([#&#8203;13033](astral-sh/uv#13033))
- Preserve newlines in `schema.json` descriptions ([#&#8203;13693](astral-sh/uv#13693))

##### Bug fixes

- Add check for using minor version link when creating a venv on Windows ([#&#8203;14252](astral-sh/uv#14252))
- Strip query parameters when parsing source URL ([#&#8203;14224](astral-sh/uv#14224))

##### Documentation

- Add a link to PyPI FAQ to clarify what per-project token is ([#&#8203;14242](astral-sh/uv#14242))

##### Preview features

- Allow symlinks in the build backend ([#&#8203;14212](astral-sh/uv#14212))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC42Mi4xIiwidXBkYXRlZEluVmVyIjoiNDAuNjIuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90Il19-->
@ashb
Copy link

ashb commented Jul 2, 2025

Any chance we could revert this @zanieb @aaron-ang?

As discussed in #14335 (comment) this handling and warning of using ~=3.12 goes counter to the documented Python Version Specifier behaviour, and this is warning rejects something that is

  1. Valid
  2. Well defined and specified, and not actually ambiguous.
  3. Was already behind handled as per the spec and in line with other tools

@zanieb
Copy link
Member

zanieb commented Jul 2, 2025

I've opened an issue for discussion so we can centralize things instead of commenting across pull requests: #14422

@notatallshaw
Copy link
Collaborator

notatallshaw commented Jul 2, 2025

As discussed in #14335 (comment) this handling and warning of using ~=3.12 goes counter to the documented Python Version Specifier behaviour, and this is warning rejects something that is

1. Valid

2. Well defined and specified, and not actually ambiguous.

3. Was already behind handled as per the spec and in line with other tools

Unfortunately 1 is true, but 2 and 3 are incorrect.

The spec on pyproject.toml says:

Corresponding core metadata field: Requires-Python

The Python version requirements of the project.

And the core metadata field says:

This field specifies the Python version(s) that the distribution is compatible with. Installation tools may look at this when picking which version of a project to install.

The value must be in the format specified in Version specifiers.

Note that it says format of a Version specifier, not semantics of a Version specifier.

The semantics of what requires-python in the pyproject.toml and Requires-Python in the core metadata field are not specified. And this has led to different tools implementing them differently. There are multiple discussions threads on this:

It clear from the discussions that:

  • The intention was that requires-python should only specify the minimum
  • The intention was requires-python should only specify the language version (e.g. it should not encode CPython patch information).

I believe the pylock.toml specification explicitly encodes these intentions in it's specification of requires-python.

It should also be noted that NO tool treats requires-python nor Requires-Python exactly like a PEP 440 Version specifier.

I was hoping to write a PEP this year on standardizing this, but I've found so many different use cases I'm concerned it's not easily possible.

I have no objections to uv handling requires-python on how it best fits it's user. But be aware this is not defined by the specification and interoperability between different tools will continue to be an issue.

@potiuk
Copy link

potiuk commented Jul 2, 2025

Unfortunately 1 is true, but 2 and 3 are incorrect.

Thanks @notatallshaw -> TIL. That's a very sad state of affairs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

error messages Messaging when something goes wrong

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Warn when project defines a requires-python that pins to a .0 patch version

5 participants