A Python package should declare its license in the License-Expression metadata field, using a valid SPDX license expression, and list its license files with License-File. PEP 639, now final, deprecates the older free text License field and the License classifiers. Doing this makes the license machine readable.
What PEP 639 changed
PEP 639 updated the Core Metadata specification to version 2.4. Two fields do the main work:
- License-Expression is an optional field containing a valid SPDX license expression. Build and publishing tools should check it, and PyPI must reject invalid values on new uploads that include it.
- License-File is an optional field, usable more than once, giving a path to a license related file. Listed files must be included in the distribution, with forward slashes in paths, no parent directory segments, and UTF-8 content.
What is deprecated
| Old way | Status |
|---|---|
| License field (free text) | Deprecated, replaced by License-Expression |
| Classifiers starting with License :: | Deprecated, replaced by License-Expression |
| Both old and new fields together | Not allowed: tools must not generate both, and PyPI rejects uploads that set both |
If a tool reads metadata with both fields, it must use License-Expression and ignore License. Tools may warn when only the old field is present.
Why it helps in diligence
Free text license fields were a common source of noise. One package might say MIT License, another MIT, another a long paragraph. A scanner then has to guess. With a valid SPDX expression, an inventory can be built and checked without guesswork. For the declared versus concluded distinction, see SPDX declared vs concluded license.
Steps for a package author
- Pick the right SPDX expression for your project, for example a single identifier or an OR expression for dual licensing.
- Put it in License-Expression, normally through your build tool's configuration.
- List your LICENSE and any NOTICE files with License-File.
- Remove License classifiers and the free text License field.
- Build and inspect the metadata before upload.
Steps for a consumer
When you scan Python dependencies, expect a mix. Newer packages use the expression field. Older ones may still have free text or classifiers. Treat a blank field as unknown and read the license file in the package, as in blank license fields.
A note on scope
The PEP page says it is now historical and that the canonical specification lives with the Python Packaging Authority. Check the current specification before you automate against it.
Safeguard does dependency scanning and SBOM generation across your repositories, and you can set policies and gates on what may merge. You can try a free scan of a public repository to see what a component inventory looks like.
Try it yourself
Open the inventory demo and look at how each dependency is listed. Notice that a clean license value makes the list easier to read.
Click through it at your own pace, or open it full screen.
Quick check
Do I need to change old releases?
No. The change applies to metadata you publish going forward. Older releases keep what they had.
Can I use both License and License-Expression?
No. The PEP says tools must not generate both, and PyPI rejects uploads that specify both.
Sources
Last reviewed: 19 October 2026.