Movatterモバイル変換


[0]ホーム

URL:


Following system colour schemeSelected dark colour schemeSelected light colour scheme

Python Enhancement Proposals

PEP 639 – Improving License Clarity with Better Package Metadata

Author:
Philippe Ombredanne <pombredanne at nexb.com>,C.A.M. Gerlach <CAM.Gerlach at Gerlach.CAM>,Karolina Surma <karolina.surma at gazeta.pl>
PEP-Delegate:
Brett Cannon <brett at python.org>
Discussions-To:
Discourse thread
Status:
Final
Type:
Standards Track
Topic:
Packaging
Created:
15-Aug-2019
Post-History:
15-Aug-2019,17-Dec-2021,10-May-2024
Resolution:
Discourse message

Table of Contents

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.

Abstract

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.

Goals

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.

Non-Goals

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.

Motivation

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:

  • It requires a great effort to duplicate the SPDX license list and keep it insync.
  • It is a hard break in backward compatibility, forcing package authorsto update to new classifiers immediately when PyPI deprecates the old ones.
  • It only covers packages under a single license;it doesn’t address projects that vendor dependencies (e.g. Setuptools),offer a choice of licenses (e.g. Packaging) or were relicensed,adapt code from other projects or contain fonts, images,examples, binaries or other assets under other licenses.
  • It requires both authors and tools understand and implement the PyPI-specificclassifier system.
  • It does not provide as clear an indicator that a packagehas adopted the new system, and should be treated accordingly.

Rationale

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:

  • SPDX and SPDX-like syntaxes are the most popularlicense expressionsin many modern package systems.
  • Most Free and Open Source Software licenses require package authors toinclude their full text in aDistribution Package.

Therefore, this PEP introduces two new Core Metadata fields:

  • License-Expression thatprovides an unambiguous way to express the license of a packageusing SPDX license expressions.
  • License-File thatoffers a standardized way to include the full text of the license(s)with the package when distributed,and allows other tools consuming theCore Metadatato locate adistribution archive’s license files.

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.

Terminology

The keywords “MUST”, “MUST NOT”, “REQUIRED”,“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL”in this document are to be interpreted as described inRFC 2119.

License terms

The license-related terminology draws heavily from theSPDX Project,particularlylicense identifier andlicense expression.

license classifier
APyPI Trove classifier(asdescribedin theCore Metadata specification)which begins withLicense::.
license expression
SPDX expression
A string with validSPDX license expression syntaxincluding one or more SPDXlicense identifier(s),which describes aProject’s license(s)and how they inter-relate.Examples:GPL-3.0-or-later,MITAND(Apache-2.0ORBSD-2-clause)
license identifier
SPDX identifier
A validSPDX short-form license identifier,as described in theAdd License-Expression field section of this PEP.This includes all valid SPDX identifiers andthe customLicenseRef-[idstring] strings conforming to theSPDX specification, clause 10.1.Examples:MIT,GPL-3.0-only,LicenseRef-My-Custom-License
root license directory
license directory
The directory under which license files are stored in aproject source tree,distribution archiveorinstalled project.Also, the root directory that their pathsrecorded in theLicense-FileCore Metadata field are relative to.Defined to be theproject root directoryfor aproject source tree orsource distribution;and a subdirectory namedlicenses ofthe directory containing thebuilt metadata—i.e., the.dist-info/licenses directory—for aBuilt Distribution orinstalled project.

Specification

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.

SPDX license expression syntax

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:

  • Any SPDX-listed license short-form identifiers that are published in theSPDX License List, version 3.17 or any later compatibleversion. Note that the SPDX working group never removes any licenseidentifiers; instead, they may choose to mark an identifier as “deprecated”.
  • The customLicenseRef-[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

Core Metadata

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.

AddLicense-Expression field

TheLicense-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.

AddLicense-File field

License-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:

  • That file MUST be included in thedistribution archive at thespecified path relative to the root license directory.
  • That file MUST be installed with theproject at that same relativepath.
  • The specified relative path MUST be consistent between project source trees,source distributions (sdists), built distributions (Wheels) andinstalled projects.
  • Inside the root license directory, packaging tools MUST reproduce thedirectory structure under which the source license files are locatedrelative to the project root.
  • Path delimiters MUST be the forward slash character (/),and parent directory indicators (..) MUST NOT be used.
  • License file content MUST be UTF-8 encoded text.

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.

DeprecateLicense field

The 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.

Deprecate license classifiers

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.

Project source metadata

This PEP specifies changes to the project’s sourcemetadata under a[project] table in thepyproject.toml file.

Add string value tolicense key

license 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"

Addlicense-files key

A 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:

  • Alphanumeric characters, underscores (_), hyphens (-) and dots (.)MUST be matched verbatim.
  • Special glob characters:*,?,** 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.
  • Path delimiters MUST be the forward slash character (/).Patterns are relative to the directory containingpyproject.toml,therefore the leading slash character MUST NOT be used.
  • Parent directory indicators (..) 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:

  • MUST treat each value as a glob pattern, and MUST raise an error if thepattern contains invalid glob syntax.
  • MUST include all files matched by a listed pattern in alldistribution archives.
  • MUST list each matched file path under aLicense-File field in theCore Metadata.
  • MUST raise an error if any individual user-specified patterndoes not match at least one file.

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.

Deprecatelicense key table subkeys

Table 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.

License files in project formats

A few additions will be made to the existing specifications.

Project source trees
PerProject source metadata section, theDeclaring Project Metadata specificationwill be updated to reflect that license file paths MUST be relative to theproject root directory; i.e. the directory containing thepyproject.toml(or equivalently, other legacy project configuration,e.g.setup.py,setup.cfg, etc).
Source distributions (sdists)
Thesdist specification will be updated to reflect that iftheMetadata-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).
Built distributions (wheels)
TheWheel specification will be updated to reflect that iftheMetadata-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.
Installed projects
TheRecording Installed Projects specification will beupdated to reflect that if theMetadata-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.

Converting legacy metadata

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.

Backwards Compatibility

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.

Security Implications

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.

How to Teach This

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:

Reference Implementation

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.

Rejected Ideas

Many alternative ideas were proposed and after a careful consideration,rejected. The exhaustive list including the rationale for rejecting can be foundin aseparate page.

Appendices

A list of auxiliary documents is provided:

Acknowledgments

  • Alyssa Coghlan
  • Kevin P. Fleming
  • Pradyun Gedam
  • Oleg Grenrus
  • Dustin Ingram
  • Chris Jerdonek
  • Cyril Roelandt
  • Luis Villa
  • Seth M. Larson
  • Ofek Lev

Copyright

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


[8]ページ先頭

©2009-2025 Movatter.jp