Important
This PEP is a historical document. The up-to-date, canonical spec,Core metadata specifications, is maintained on thePyPA specs page.
×
See thePyPA specification update process for how to propose changes.
This PEP defines a specification how licenses are documented in the Pythonprojects.
To achieve that, it:
This will make license declaration simpler and less ambiguous forpackage authors to create, end users to understand,and tools to programmatically process.
The changes will update theCore Metadata specification to version 2.4.
This PEP’s scope is limited to covering new mechanisms for documentingthe license of adistribution package, specifically defining:
The changes that this PEP requires have been designed to minimize impact andmaximize backward compatibility.
This PEP doesn’t recommend any particular license to be chosen by anyparticular package author.
If projects decide not to use the new fields, no additional restrictions areimposed by this PEP when uploading to PyPI.
This PEP also is not about license documentation for individual files,though this is asurveyed topicin an appendix, nor does it intend to cover cases where thesource distribution andbinary distribution packages don’t havethe same licenses.
Software must be licensed in order for anyone other than its creator todownload, use, share and modify it.Today, there are multiple fields where licensesare documented inCore Metadata,and there are limitations to what can be expressed in each of them.This often leads to confusion both for package authorsand end users, including distribution re-packagers.
This has triggered a number of license-related discussions and issues,including onoutdated and ambiguous PyPI classifiers,license interoperability with other ecosystems,too many confusing license metadata options,limited support for license files in the Wheel project, andthe lack of precise license metadata.
As a result, on average, Python packages tend to have more ambiguous andmissing license information than other common ecosystems. This is supported bythestatistics page of theClearlyDefined project, anOpen Source Initiative effort to helpimprove licensing clarity of other FOSS projects, covering all packagesfrom PyPI, Maven, npm and Rubygems.
The current license classifiers could be extended to include the full range ofthe SPDX identifiers while deprecating the ambiguous classifiers(such asLicense::OSIApproved::BSDLicense).
However, there are multiple arguments against such an approach:
A survey was conducted to map the existing license metadatadefinitions in thePython ecosystem and avariety of other packaging systems, Linux distributions,language ecosystems and applications.
The takeaways from the survey have guided the recommendations of this PEP:
Therefore, this PEP introduces two new Core Metadata fields:
Furthermore, this specification builds uponexisting practice in theSetuptools andWheel projects.An up-to-date version of the current draft of this PEP isimplemented in theHatch packaging tool, and an earlier draft of thelicense files portionisimplemented in Setuptools.
The keywords “MUST”, “MUST NOT”, “REQUIRED”,“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL”in this document are to be interpreted as described inRFC 2119.
The license-related terminology draws heavily from theSPDX Project,particularlylicense identifier andlicense expression.
License::.GPL-3.0-or-later,MITAND(Apache-2.0ORBSD-2-clause)LicenseRef-[idstring] strings conforming to theSPDX specification, clause 10.1.Examples:MIT,GPL-3.0-only,LicenseRef-My-Custom-Licenselicenses ofthe directory containing thebuilt metadata—i.e., the.dist-info/licenses directory—for aBuilt Distribution orinstalled project.The changes necessary to implement this PEP include:
Note that the guidance on errors and warnings is for tools’ default behavior;they MAY operate more strictly if users explicitly configure them to do so,such as by a CLI flag or a configuration option.
This PEP adopts the SPDX license expression syntax asdocumented in theSPDX specification, eitherVersion 2.2 or a later compatible version.
A license expression can use the followinglicense identifiers:
LicenseRef-[idstring] string(s), where[idstring] is a unique string containing letters, numbers,. and/or-, to identify licenses that are not included in the SPDXlicense list. The custom identifiers must follow the SPDX specification,clause 10.1 of the given specification version.Examples of valid SPDX expressions:
MITBSD-3-ClauseMIT AND (Apache-2.0 OR BSD-2-Clause)MIT OR GPL-2.0-or-later OR (FSFUL AND BSD-2-Clause)GPL-3.0-only WITH Classpath-Exception-2.0 OR BSD-3-ClauseLicenseRef-Special-License OR CC0-1.0 OR UnlicenseLicenseRef-Proprietary
Examples of invalid SPDX expressions:
Use-it-after-midnightApache-2.0 OR 2-BSD-ClauseLicenseRef-License with spacesLicenseRef-License_with_underscores
The error and warning guidance in this section applies to build andpublishing tools; end-user-facing install tools MAY be less strict thanmentioned here when encountering malformed metadatathat does not conform to this specification.
As it adds new fields, this PEP updates the Core Metadata version to 2.4.
License-Expression fieldTheLicense-Expression optionalCore Metadata fieldis specified to contain a text stringthat is a valid SPDXlicense expression,asdefined above.
Build and publishing tools SHOULDcheck that theLicense-Expression field contains a valid SPDX expression,including the validity of the particular license identifiers(asdefined above).Tools MAY halt execution and raise an error when an invalid expression is found.If tools choose to validate the SPDX expression, they also SHOULDstore a case-normalized version of theLicense-Expressionfield using the reference case for each SPDX license identifier and uppercasefor theAND,OR andWITH keywords.Tools SHOULD report a warning and publishing tools MAY raise an errorif one or more license identifiershave been marked as deprecated in theSPDX License List.
For all newly-uploadeddistribution archivesthat include aLicense-Expression field,thePython Package Index (PyPI) MUSTvalidate that they contain a valid, case-normalized license expression withvalid identifiers (asdefined above)and MUST reject uploads that do not.Custom license identifiers which conform to the SPDX specificationare considered valid.PyPI MAY reject an upload for using a deprecated license identifier,so long as it was deprecated as of the above-mentioned SPDX License Listversion.
License-File fieldLicense-File is an optionalCore Metadata field.Each instance contains the stringrepresentation of the path of a license-related file. The path is locatedwithin theproject source tree, relative to theproject root directory.It is a multi-use field that may appear zero ormore times and each instance lists the path to one such file. Files specifiedunder this field could include license text, author/attribution information,or other legal notices that need to be distributed with the package.
Asspecified by this PEP, its valueis also that file’s path relative to theroot license directoryin bothinstalled projectsand the standardizedDistribution Package types.
If aLicense-File is listed in aSource Distribution orBuilt Distribution’s Core Metadata:
/),and parent directory indicators (..) MUST NOT be used.Build tools MAY and publishing tools SHOULD produce an informative warningif a built distribution’s metadata contains noLicense-File entries,and publishing tools MAY but build tools MUST NOT raise an error.
For all newly-uploadeddistribution archives that include one or moreLicense-File fields in their Core Metadataand declare aMetadata-Version of2.4 or higher,PyPI SHOULD validate that all specified files are present in thatdistribution archives,and MUST reject uploads that do not validate.
License fieldThe legacy unstructured-textLicenseCore Metadata fieldis deprecated and replaced by the newLicense-Expression field.The fields are mutually exclusive.Tools which generate Core Metadata MUST NOT create both these fields.Tools which read Core Metadata, when dealing with both these fields presentat the same time, MUST read the value ofLicense-Expression and MUSTdisregard the value of theLicense field.
If only theLicense field is present, tools MAY issue a warninginforming users it is deprecated and recommendingLicense-Expressioninstead.
For all newly-uploadeddistribution archives that include aLicense-Expression field, thePython Package Index (PyPI) MUSTreject any that specify bothLicense andLicense-Expression fields.
TheLicense field may be removed from a new version of the specificationin a future PEP.
Usinglicense classifiersin theClassifierCore Metadata field(described in the Core Metadata specification)is deprecated and replaced by the more preciseLicense-Expression field.
If theLicense-Expression field is present, build tools MAY raise an errorif one or more license classifiersis included in aClassifier field, and MUST NOT addsuch classifiers themselves.
Otherwise, if this field contains a license classifier,tools MAY issue a warning informing users such classifiersare deprecated, and recommendingLicense-Expression instead.For compatibility with existing publishing and installation processes,the presence of license classifiers SHOULD NOT raise an error unlessLicense-Expression is also provided.
New license classifiers MUST NOT beadded to PyPI;users needing them SHOULD use theLicense-Expression field instead.License classifiers may be removed from a new version of the specificationin a future PEP.
This PEP specifies changes to the project’s sourcemetadata under a[project] table in thepyproject.toml file.
license keylicense key in the[project] table is defined to contain a top-levelstring value. It is a valid SPDX license expression asdefined in this PEP.Its value maps to theLicense-Expression field in the core metadata.
Build tools SHOULD validate and perform case normalization of the expressionas described in theAdd License-Expression field section,outputting an error or warning as specified.
Examples:
[project]license="MIT"[project]license="MIT AND (Apache-2.0 OR BSD-2-clause)"[project]license="MIT OR GPL-2.0-or-later OR (FSFUL AND BSD-2-Clause)"[project]license="LicenseRef-Proprietary"
license-files keyA newlicense-files key is added to the[project] table for specifyingpaths in the project source tree relative topyproject.toml to file(s)containing licenses and other legal notices to be distributed with the package.It corresponds to theLicense-File fields in the Core Metadata.
Its value is an array of strings which MUST contain valid glob patterns,as specified below:
_), hyphens (-) and dots (.)MUST be matched verbatim.*,?,** and character ranges:[]containing only the verbatim matched characters MUST be supported.Within[...], the hyphen indicates a locale-agnostic range (e.g.a-z,order based on Unicode code points).Hyphens at the start or end are matched literally./).Patterns are relative to the directory containingpyproject.toml,therefore the leading slash character MUST NOT be used...) MUST NOT be used.Any characters or character sequences not covered by this specification areinvalid. Projects MUST NOT use such values.Tools consuming this field SHOULD reject invalid values with an error.
Tools MUST assume that license file content is valid UTF-8 encoded text,and SHOULD validate this and raise an error if it is not.
Literal paths (e.g.LICENSE) are treated as valid globs which means theycan also be defined.
Build tools:
License-File field in theCore Metadata.If thelicense-files key is present andis set to a value of an empty array, then tools MUST NOT include anylicense files and MUST NOT raise an error.
Examples of valid license files declaration:
[project]license-files=["LICEN[CS]E*","AUTHORS*"][project]license-files=["licenses/LICENSE.MIT","licenses/LICENSE.CC0"][project]license-files=["LICENSE.txt","licenses/*"][project]license-files=[]
Examples of invalid license files declaration:
[project]license-files=["..\LICENSE.MIT"]
Reason:.. must not be used.\ is an invalid path delimiter,/ must be used.
[project]license-files=["LICEN{CSE*"]
Reason: “LICEN{CSE*” is not a valid glob.
license key table subkeysTable values for thelicense key in the[project] table,including thetext andfile table subkeys, are now deprecated.If the newlicense-files key is present,build tools MUST raise an error if thelicense key is definedand has a value other than a single top-level string.
If the newlicense-files key is not presentand thetext subkey is present in alicense table,tools SHOULD issue a warning informing users it is deprecatedand recommending a license expression as a top-level string key instead.
Likewise, if the newlicense-files key is not presentand thefile subkey is present in thelicense table,tools SHOULD issue a warning informing users it is deprecated and recommendingthelicense-files key instead.
If the specified licensefile is present in the source tree,build tools SHOULD use it to fill theLicense-File fieldin the core metadata, and MUST include the specified fileas if it were specified in alicense-file field.If the file does not exist at the specified path,tools MUST raise an informative error as previously specified.
Table values for thelicense key MAY be removedfrom a new version of the specification in a future PEP.
A few additions will be made to the existing specifications.
pyproject.toml(or equivalently, other legacy project configuration,e.g.setup.py,setup.cfg, etc).Metadata-Version is2.4 or greater,the sdist MUST contain any license files specified bytheLicense-File fieldin thePKG-INFO at their respective pathsrelative to the of the sdist(containing thepyproject.toml and thePKG-INFO Core Metadata).Metadata-Version is2.4 or greater and one or moreLicense-File fields is specified, the.dist-info directory MUSTcontain alicenses subdirectory, which MUST contain the files listedin theLicense-File fields in theMETADATA file at their respectivepaths relative to thelicenses directory.Metadata-Version is2.4 or greaterand one or moreLicense-File fields is specified, the.dist-infodirectory MUST contain alicenses subdirectory which MUST containthe files listed in theLicense-File fields in theMETADATA fileat their respective paths relative to thelicenses directory,and that any files in this directory MUST be copied from wheelsby install tools.Tools MUST NOT use the contents of thelicense.text[project] key(or equivalent tool-specific format),license classifiers or the value of the Core MetadataLicense fieldto fill the top-level string value of thelicense keyor the Core MetadataLicense-Expression fieldwithout informing the user and requiring unambiguous, affirmative user actionto select and confirm the desired license expression value before proceeding.
Tool authors, who need to automatically convert license classifiers toSPDX identifiers, can use therecommendation prepared bythe PEP authors.
Adding a newLicense-Expression Core Metadata field and a top-level stringvalue for thelicense key in thepyproject.toml[project] tableunambiguously means support for the specification in this PEP. This avoids therisk of new tooling misinterpreting a license expression as a free-form licensedescription or vice versa.
The legacy deprecated Core MetadataLicense field,license key tablesubkeys (text andfile) in thepyproject.toml[project] tableand license classifiers retain backwards compatibility. A removal isleft to a future PEP and a new version of the Core Metadata specification.
Specification of the newLicense-File Core Metadata field and adding thefiles in the distribution is designed to be largely backwards-compatible withthe existing use of that field in many packaging tools.The newlicense-files key in the[project] table ofpyproject.toml will only have an effect once users and tools adopt it.
This PEP specifies that license files should be placed in a dedicatedlicenses subdir of.dist-info directory. This is new and ensures thatwheels following this PEP will have differently-located licenses relative tothose produced via the previous installer-specific behavior. This is furthersupported by a new metadata version.
This also resolves current issues where license files are accidentallyreplaced if they have the same names in different places, making wheelsundistributable without noticing. It also prevents conflicts with othermetadata files in the same directory.
The additions will be made to the source distribution (sdist), builtdistribution (wheel) and installed project specifications. They documentbehaviors allowed under their current specifications, and gate them behind thenew metadata version.
This PEP proposes PyPI implement validation of the newLicense-Expression andLicense-File fields, which has no effect onnew and existing packages uploaded unless they explicitly opt in to usingthese new fields and fail to follow the specification correctly.Therefore, this does not have a backward compatibility impact, and guaranteesforward compatibility by ensuring all distributions uploaded to PyPI with thenew fields conform to the specification.
This PEP has no foreseen security implications: theLicense-Expressionfield is a plain string and theLicense-File fields are file paths.Neither introduces any known new security concerns.
A majority of packages use a single license which makes the case simple:a single license identifier is a valid license expression.
Users of packaging tools will learn the valid license expression of theirpackage through the messages issued by the tools when they detect invalidones, or when the deprecatedLicense field or license classifiers are used.
If an invalidLicense-Expression is used, the users will not be ableto publish their package to PyPI and an error message will help themunderstand they need to use SPDX identifiers.It will be possible to generate a distribution with incorrect license metadata,but not to publish one on PyPI or any other index server that enforcesLicense-Expression validity.For authors using the now-deprecatedLicense field or license classifiers,packaging tools may warn them and inform them of the replacement,License-Expression.
Tools may also help with the conversion and suggest a license expression inmany common cases:
License valuein project source metadata and convert that to a license expression,as alsospecified in this PEP.Tools will need to support parsing and validating license expressions in theLicense-Expression field if they decide to implement this part of thespecification.It’s up to the tools whether they prefer to implement the validation on theirside (e.g. likehatch) or use one of the availablePython libraries (e.g.license-expression).This PEP does not mandate using any specific library and leaves it to thetools authors to choose the best implementation for their projects.
Many alternative ideas were proposed and after a careful consideration,rejected. The exhaustive list including the rationale for rejecting can be foundin aseparate page.
A list of auxiliary documents is provided:
This document is placed in the public domain or under theCC0-1.0-Universal license, whichever is more permissive.
Source:https://github.com/python/peps/blob/main/peps/pep-0639.rst
Last modified:2025-01-24 23:56:07 GMT