Skip to content

feat: use PEP 639 where possible #592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions docs/_includes/pyproject.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ The metadata is specified in a [standards-based][metadata] format:
name = "package"
description = "A great package."
readme = "README.md"
license = "BSD-3-Clause"
license-files = ["LICENSE"]
authors = [
{ name = "My Name", email = "me@email.com" },
]
Expand All @@ -21,7 +23,6 @@ dependencies = [

classifiers = [
"Development Status :: 4 - Beta",
"License :: OSI Approved :: BSD License",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
Expand All @@ -47,19 +48,28 @@ or [Whey](https://whey.readthedocs.io/en/latest/configuration.html). Note that

### License

The license can be done one of two ways. The classic convention (shown above)
uses one or more [Trove Classifiers][] to specify the license. The other way is
to use the `license` field and an [SPDX identifier expression][spdx]:
The license can be done one of two ways.

```toml
license = "BSD-3-Clause"
```
The modern way is to use the `license` field and an [SPDX identifier
expression][spdx]. You can specify a list of files globs in `license-files`.
Currently, `hatchling>=1.26`, `flit-core>=1.11`, `pdm-backend>=2.4`,
`setuptools>=77`, and `scikit-build-core>=0.12` support this. Only `maturin`,
`meson-python`, and `flit-core` do not support this yet.

The classic convention uses one or more [Trove Classifiers][] to specify the
license. There also was a `license.file` field, required by `meson-python`, but
other tools often did the wrong thing (such as load the entire file into the
metadata's free-form one line text field that was intended to describe
deviations from the classifier license(s)).

You can also specify files to include with the `license-files` field.
```
classifiers = [
"License :: OSI Approved :: BSD License",
]
```

You should not include the `License ::` classifiers if you use the `license`
field {% rr PP007 %}. Some backends do not support this fully yet (notably
Poetry and Setuptools).
field {% rr PP007 %}.

### Extras

Expand Down
9 changes: 9 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,15 @@ def dist(session: nox.Session, backend: str, vcs: bool) -> None:
# Check for LICENSE in SDist
with tarfile.open(sdist) as tf:
names = tf.getnames()
if backend not in {"mesonpy", "poetry", "maturin"}:
(metadata_path,) = (
n for n in names if n.endswith("PKG-INFO") and "egg-info" not in n
)
with tf.extractfile(metadata_path) as mfile:
info = mfile.read().decode("utf-8")
if "License-Expression: BSD-3-Clause" not in info:
msg = "License expression not found in METADATA"
session.error(msg)
if not any(n.endswith("LICENSE") for n in names):
msg = f"license file missing from {backend} vcs={vcs}'s sdist. Found: {names}"
session.error(msg)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ authors = [
]
description = "Review repos for compliance to the Scientific-Python development guidelines"
requires-python = ">=3.10"
license = 'BSD-3-Clause'
license = "BSD-3-Clause"
classifiers = [
"Development Status :: 4 - Beta",
"Environment :: Console",
Expand Down
33 changes: 22 additions & 11 deletions {{cookiecutter.project_name}}/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
[build-system]
{%- if cookiecutter.backend == "pdm" %}
requires = ["pdm-backend"]
requires = ["pdm-backend>=2.4"]
build-backend = "pdm.backend"
{%- elif cookiecutter.backend == "maturin" %}
requires = ["maturin>=0.15,<2"]
build-backend = "maturin"
{%- elif cookiecutter.backend == "hatch" %}
{%- if cookiecutter.vcs %}
requires = ["hatchling", "hatch-vcs"]
requires = ["hatchling>=1.26", "hatch-vcs"]
{%- else %}
requires = ["hatchling"]
requires = ["hatchling>=1.26"]
{%- endif %}
build-backend = "hatchling.build"
{%- elif cookiecutter.backend == "setuptools" %}
{%- if cookiecutter.vcs %}
requires = ["setuptools>=61", "setuptools_scm[toml]>=7"]
requires = ["setuptools>=77", "setuptools_scm[toml]>=7"]
{%- else %}
requires = ["setuptools>=61"]
requires = ["setuptools>=77"]
{%- endif %}
build-backend = "setuptools.build_meta"
{%- elif cookiecutter.backend == "flit" %}
{%- if cookiecutter.vcs %}
requires = ["flit_scm"]
requires = ["flit_scm", "flit_core>=3.11"]
build-backend = "flit_scm:buildapi"
{%- else %}
requires = ["flit_core>=3.4"]
requires = ["flit_core>=3.11"]
build-backend = "flit_core.buildapi"
{%- endif %}
{%- elif cookiecutter.backend == "pybind11" %}
{%- if cookiecutter.vcs %}
requires = ["setuptools>=61", "setuptools_scm[toml]>=7", "pybind11"]
requires = ["setuptools>=77", "setuptools_scm[toml]>=7", "pybind11"]
{%- else %}
requires = ["setuptools>=61", "pybind11"]
requires = ["setuptools>=77", "pybind11"]
{%- endif %}
build-backend = "setuptools.build_meta"
{%- elif cookiecutter.backend == "skbuild" %}
requires = ["pybind11", "scikit-build-core>=0.10"]
requires = ["pybind11", "scikit-build-core>=0.11"]
build-backend = "scikit_build_core.build"
{%- elif cookiecutter.backend == "mesonpy" %}
requires = ["meson-python", "pybind11"]
Expand Down Expand Up @@ -66,20 +66,31 @@ maintainers = [
{%- endif %}
description = "{{ cookiecutter.project_short_description }}"
readme = "README.md"
{%- if cookiecutter.backend in ['flit', 'mesonpy'] %}
{%- if cookiecutter.backend not in ['poetry', 'mesonpy', 'maturin'] %}
{%- if cookiecutter.license == "BSD" %}
license = "BSD-3-Clause"
{%- elif cookiecutter.license == "Apache" %}
license = "Apache-2.0"
{%- elif cookiecutter.license == "MIT" %}
Comment on lines +69 to +74
Copy link
Preview

Copilot AI May 2, 2025

Choose a reason for hiding this comment

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

Review the updated conditional for including the license field to ensure that excluding 'poetry', 'mesonpy', and 'maturin' aligns with the intended metadata configuration for these backends.

Suggested change
{%- if cookiecutter.backend not in ['poetry', 'mesonpy', 'maturin'] %}
{%- if cookiecutter.license == "BSD" %}
license = "BSD-3-Clause"
{%- elif cookiecutter.license == "Apache" %}
license = "Apache-2.0"
{%- elif cookiecutter.license == "MIT" %}
{%- if cookiecutter.license == "BSD" %}
{%- if cookiecutter.backend == "mesonpy" %}
license.file = "LICENSE"
{%- else %}
license = "BSD-3-Clause"
{%- endif %}
{%- elif cookiecutter.license == "Apache" %}
{%- if cookiecutter.backend == "mesonpy" %}
license.file = "LICENSE"
{%- else %}
license = "Apache-2.0"
{%- endif %}
{%- elif cookiecutter.license == "MIT" %}
{%- if cookiecutter.backend == "mesonpy" %}
license.file = "LICENSE"
{%- else %}

Copilot uses AI. Check for mistakes.

license = "MIT"
{%- endif %}
{%- endif %}
{%- if cookiecutter.backend in ['mesonpy'] %}
license.file = "LICENSE"
{%- endif %}
requires-python = ">=3.9"
classifiers = [
"Development Status :: 1 - Planning",
"Intended Audience :: Science/Research",
"Intended Audience :: Developers",
{%- if cookiecutter.backend in ['poetry', 'mesonpy', 'maturin'] %}
{%- if cookiecutter.license == "BSD" %}
"License :: OSI Approved :: BSD License",
{%- elif cookiecutter.license == "Apache" %}
"License :: OSI Approved :: Apache Software License",
{%- elif cookiecutter.license == "MIT" %}
"License :: OSI Approved :: MIT License",
{%- endif %}
{%- endif %}
"Operating System :: OS Independent",
"Programming Language :: Python",
Expand Down
Loading