Skip to content

Add support for License-Expression parsing (PEP 639)#213

Merged
reactive-firewall merged 3 commits into
raimon49:dev-5.5.0from
cdce8p:license-expression
Oct 10, 2025
Merged

Add support for License-Expression parsing (PEP 639)#213
reactive-firewall merged 3 commits into
raimon49:dev-5.5.0from
cdce8p:license-expression

Conversation

@cdce8p
Copy link
Copy Markdown
Contributor

@cdce8p cdce8p commented Oct 11, 2024

PEP 639 has been (provisionally) accepted recently. hatch added support1 for it early on and so the first packages which store the license metadata inside the License-Expression field start popping up. E.g. for ftfy it looks like this

...
License-Expression: Apache-2.0
License-File: LICENSE.txt
...

This PR adds the basic parsing support without any validation similar to the existing behavior for the License metadata field or the classifier. It might make sense to add the validation at a later point though.

To keep the changes to a minimum, the behavior of --from=mixed is preserved. However:

Caution

Breaking change: The --from=all output now includes the License-Expression value.

Fixes #225

Footnotes

  1. https://hatch.pypa.io/1.9/config/metadata/#spdx-expression

@codecov
Copy link
Copy Markdown

codecov Bot commented Oct 11, 2024

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.14%. Comparing base (3fbf20f) to head (1ec35a3).
⚠️ Report is 6 commits behind head on dev-5.5.0.

Additional details and impacted files
@@            Coverage Diff             @@
##           dev-5.5.0     #213   +/-   ##
==========================================
  Coverage      99.13%   99.14%           
==========================================
  Files              1        1           
  Lines            462      466    +4     
==========================================
+ Hits             458      462    +4     
  Misses             4        4           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@stefan6419846
Copy link
Copy Markdown

Isn't the proposed handling against PEP 639? According to https://packaging.python.org/en/latest/specifications/core-metadata/#license, the following holds true:

As of Metadata 2.4, License and License-Expression are mutually exclusive. If both are specified, tools which parse metadata will disregard License and PyPI will reject uploads. See PEP 639.

With PyPI not allowing both keys to be set and License-Expression taking precedence otherwise, wouldn't it make more sense to retrieve license-expression as the first variant in METADATA_KEYS["license"]? This would avoid the breaking change as well.

@cdce8p
Copy link
Copy Markdown
Contributor Author

cdce8p commented Oct 30, 2024

With PyPI not allowing both keys to be set and License-Expression taking precedence otherwise, wouldn't it make more sense to retrieve license-expression as the first variant in METADATA_KEYS["license"]?

Yeah, you're correct. License-Expression should take precedence and all other values should be ignored. My initial thought was to preserve backwards compatibility as much as possible and not change the precedence order on an existing option. In practice it shouldn't make much of a difference as "normally" only one should be defined (either License-Expression or License metadata / classifier). Anyway pushed a new commit to update the logic.

This would avoid the breaking change as well.

Not quite sure about that one. The breaking change is in the --from=all output. It adds a new column, so for users who depend on the exact form it's a breaking change.

Julian added a commit to python-jsonschema/jsonschema that referenced this pull request Dec 28, 2024
The License field is deprecated, as is the trove classifier.

Note that pip show does not support properly detecting these yet,
but it will.

Note also that `pip-licenses` does not support PEP 639 (see
raimon49/pip-licenses#213) the implications of which are that we are
already broken (the `license_check` noxenv fails because of packages
already using the newer standard). This doesn't fix that yet. AFAICT no
tool exists that does this properly yet/now. So let's see... I guess we
reimplement that functionality?!

Refs: https://peps.python.org/pep-0639/
Refs: pypa/pip#13112
Refs: pypa/pip#6677
Copy link
Copy Markdown

@SMoraisAnsys SMoraisAnsys left a comment

Choose a reason for hiding this comment

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

Thanks for this PR ! Could you update the dependency file to add a package using license expression ? I proposed attrs but any other package doing it is fine :)

Comment thread test_piplicenses.py
Comment thread test_piplicenses.py
@cdce8p
Copy link
Copy Markdown
Contributor Author

cdce8p commented Jan 28, 2025

Could you update the dependency file to add a package using license expression ? I proposed attrs but any other package doing it is fine :)

I'd prefer not to add an additional test dependency just for that. The last prettytable release also added License-Expression. Once #222 is merged, I can update this PR / or do a followup to enable the asserts.

@SMoraisAnsys
Copy link
Copy Markdown

Could you update the dependency file to add a package using license expression ? I proposed attrs but any other package doing it is fine :)

I'd prefer not to add an additional test dependency just for that. The last prettytable release also added License-Expression. Once #222 is merged, I can update this PR / or do a followup to enable the asserts.

Attrs is already a dependency (see the top of the dependency file)
But sure, prettiable is a good target :)

@cdce8p
Copy link
Copy Markdown
Contributor Author

cdce8p commented Jan 28, 2025

Attrs is already a dependency (see the top of the dependency file) But sure, prettiable is a good target :)

It's only a transitive dependency on an old pytest version. Will be removed with #217 it seems. Anyway, I'd like to keep dependency bumps separate. Will update the asserts here, if #217 and / or #222 ever gets merged.

@SMoraisAnsys
Copy link
Copy Markdown

@raimon49 Sorry for the direct ping but this package doesn't seem to have much activity since 6 months. Could you have a look at this PR or should we assume the repo to be dead and move with a fork ?

@martin-traverse
Copy link
Copy Markdown

Hi - any chance of getting something merged for this? Packages are starting to use the new standard. On our project we've started blocking some updates, but that can only be done for so long. Getting a new release onto PyPI that supports the new standard would be really helpful.

@bd-gpasternak
Copy link
Copy Markdown

desperately asking that this get merged so that we don't have to perform surgery to roll our own pip license code.

Comment thread piplicenses.py
@johnthagen
Copy link
Copy Markdown
Contributor

For those in need of this, consider pip-licenses-cli, a maintained fork that is a drop-in replacement that supports PEP 639

@reactive-firewall reactive-firewall added the duplicate This issue or pull request already exists label Oct 9, 2025
Comment thread piplicenses.py Outdated
Comment thread piplicenses.py
Comment thread piplicenses.py
Comment thread test_piplicenses.py
@reactive-firewall reactive-firewall self-assigned this Oct 10, 2025
@reactive-firewall reactive-firewall changed the base branch from master to dev-5.5.0 October 10, 2025 02:21
Minor change to avoid possible bug risk.
@reactive-firewall reactive-firewall self-requested a review October 10, 2025 02:23
@reactive-firewall reactive-firewall dismissed SMoraisAnsys’s stale review October 10, 2025 02:26

Previous reviews are sufficiently resolved.

Copy link
Copy Markdown
Collaborator

@reactive-firewall reactive-firewall left a comment

Choose a reason for hiding this comment

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

👍 LGTM;

☑️ PR is approved for dev branch!

@cdce8p Thank you for this PR!

@reactive-firewall reactive-firewall merged commit 89f8318 into raimon49:dev-5.5.0 Oct 10, 2025
6 checks passed
@cdce8p cdce8p deleted the license-expression branch October 10, 2025 10:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

duplicate This issue or pull request already exists enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

request: support PEP 639

9 participants