astral-sh / uv

An extremely fast Python package and project manager, written in Rust.
https://docs.astral.sh/uv
Apache License 2.0
27.7k stars 797 forks source link

Automatic Python Trove Classifiers #8716

Open harkabeeparolus opened 3 weeks ago

harkabeeparolus commented 3 weeks ago

Summary

I wish uv would provide default automatic trove classifiers for Python versions when building wheels.

Poetry adds automatic default Python version (and license) trove classifiers. This improves the package metadata when uploading to PyPI, and means that the developer doesn't have to manage these versions manually as the project's Python requirements change.

Suggested Implementation

Thanks to @konstin for pointing me towards dynamic as a solution.

Examples

Example (with Poetry version 1.8.4):

$ poetry new foo && cd foo
$ sed -i -e $'/^version =/a\\\nlicense = "GPL-3.0-or-later"\n' pyproject.toml
$ poetry build
$ unzip -p dist/foo-0.1.0-py3-none-any.whl foo-0.1.0.dist-info/METADATA
Metadata-Version: 2.1
Name: foo
Version: 0.1.0
Summary:
License: GPL-3.0-or-later
Author: Yeeg9yoo Ohl4eida
Author-email: boo6gima@choo7eir.com
Requires-Python: >=3.9,<4.0
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Description-Content-Type: text/markdown

Compare this to uv 0.4.29 (85f9a0d0e 2024-10-30):

$ uv init --package foo && cd foo
$ sed -i -e $'/^version =/a\\\nlicense = "GPL-3.0-or-later"\n' pyproject.toml
$ uv build
$ unzip -p dist/foo-0.1.0-py3-none-any.whl foo-0.1.0.dist-info/METADATA
Metadata-Version: 2.3
Name: foo
Version: 0.1.0
Summary: Add your description here
Author-email: Yeeg9yoo Ohl4eida <boo6gima@choo7eir.com>
License-Expression: GPL-3.0-or-later
Requires-Python: >=3.13

(Interestingly, this metadata is actually invalid since it breaks the specification. The License-Expression field is not available until Metadata-Version: 2.4 or later. šŸ˜³)

HenriBlacksmith commented 3 weeks ago

Could they automatically be added to the pyproject.toml too? (Not sure when but it could be even better)

harkabeeparolus commented 3 weeks ago

Could they automatically be added to the pyproject.toml too? (Not sure when but it could be even better)

Preferably not, in my opinion... My point is that adding default classifiers automatically to the wheel enables you to specify versions in one place only, instead of copy-pasting or editing them in several different places.

A single source of truth is better than multiple manually managed sources of confusion. šŸ˜‰

konstin commented 3 weeks ago

Specification note: PEP 621 only allows us to do this if with dynamic = ["classifiers"]. Poetry is allowed to do this since they are not using the [project] table.

HenriBlacksmith commented 3 weeks ago

Could they automatically be added to the pyproject.toml too? (Not sure when but it could be even better)

Preferably not, in my opinion... My point is that adding default classifiers automatically to the wheel enables you to specify versions in one place only, instead of copy-pasting or editing them in several different places.

A single source of truth is better than multiple manually managed sources of confusion. šŸ˜‰

Maybe those are two different features then, one could be a command to update "static" classifiers in the pyproject.toml and another one a setting to enrich classifiers in the build (maybe via the dynamic mode)

harkabeeparolus commented 3 weeks ago

Specification note: PEP 621 only allows us to do this if with dynamic = ["classifiers"]. Poetry is allowed to do this since they are not using the [project] table.

That's a good point!

I'm not familiar enough with PEP 621, so I wonder... Would it be possible to use dynamic = ["classifiers"] to get default values, and at the same time also use manually specified values to override the defaults or to specify additional classifiers?

harkabeeparolus commented 3 weeks ago

Specification note: PEP 621 only allows us to do this if with dynamic = ["classifiers"]. Poetry is allowed to do this since they are not using the [project] table.

Update:

I browsed through the specifications for pyproject.toml as well as Core metadata, which are based partly on PEP 621 and 643, and I see no problems with my suggestion.

While both specifying core metadata AND declaring it to be dynamic is not explicitly mentioned in the specs, it is also clearly not forbidden, as far as I can tell.

In other words, we could certainly have build backends that provide default Python version trove classifiers if unspecified AND if classifiers is declared as dynamic... And we could include dynamic = ["classifiers"] in the uv init templates for the backends that support this feature.