python-peps/pep-0639/index.html

849 lines
76 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 639 Improving License Clarity with Better Package Metadata | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0639/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 639 Improving License Clarity with Better Package Metadata | peps.python.org'>
<meta property="og:description" content="This PEP defines a specification how licenses are documented in the Python projects.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0639/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP defines a specification how licenses are documented in the Python projects.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 639</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 639 Improving License Clarity with Better Package Metadata</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Philippe Ombredanne &lt;pombredanne&#32;&#97;t&#32;nexb.com&gt;,
C.A.M. Gerlach &lt;CAM.Gerlach&#32;&#97;t&#32;Gerlach.CAM&gt;,
Karolina Surma &lt;karolina.surma&#32;&#97;t&#32;gazeta.pl&gt;</dd>
<dt class="field-even">PEP-Delegate<span class="colon">:</span></dt>
<dd class="field-even">Brett Cannon &lt;brett&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-odd">Discussions-To<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="https://discuss.python.org/t/53020">Discourse thread</a></dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Provisionally accepted but additional feedback needed">Provisional</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Topic<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="../topic/packaging/">Packaging</a></dd>
<dt class="field-odd">Created<span class="colon">:</span></dt>
<dd class="field-odd">15-Aug-2019</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="https://discuss.python.org/t/2154" title="Discourse thread">15-Aug-2019</a>,
<a class="reference external" href="https://discuss.python.org/t/12622" title="Discourse thread">17-Dec-2021</a>,
<a class="reference external" href="https://discuss.python.org/t/53020" title="Discourse thread">10-May-2024</a></dd>
<dt class="field-odd">Resolution<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="https://discuss.python.org/t/53020/106">Discourse message</a></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#provisional-acceptance">Provisional Acceptance</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#goals">Goals</a></li>
<li><a class="reference internal" href="#non-goals">Non-Goals</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#terminology">Terminology</a><ul>
<li><a class="reference internal" href="#license-terms">License terms</a></li>
</ul>
</li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#spdx-license-expression-syntax">SPDX license expression syntax</a></li>
<li><a class="reference internal" href="#core-metadata">Core Metadata</a><ul>
<li><a class="reference internal" href="#add-license-expression-field">Add <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field</a></li>
<li><a class="reference internal" href="#add-license-file-field">Add <code class="docutils literal notranslate"><span class="pre">License-File</span></code> field</a></li>
<li><a class="reference internal" href="#deprecate-license-field">Deprecate <code class="docutils literal notranslate"><span class="pre">License</span></code> field</a></li>
<li><a class="reference internal" href="#deprecate-license-classifiers">Deprecate license classifiers</a></li>
</ul>
</li>
<li><a class="reference internal" href="#project-source-metadata">Project source metadata</a><ul>
<li><a class="reference internal" href="#add-string-value-to-license-key">Add string value to <code class="docutils literal notranslate"><span class="pre">license</span></code> key</a></li>
<li><a class="reference internal" href="#add-license-files-key">Add <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key</a></li>
<li><a class="reference internal" href="#deprecate-license-key-table-subkeys">Deprecate <code class="docutils literal notranslate"><span class="pre">license</span></code> key table subkeys</a></li>
</ul>
</li>
<li><a class="reference internal" href="#license-files-in-project-formats">License files in project formats</a></li>
<li><a class="reference internal" href="#converting-legacy-metadata">Converting legacy metadata</a></li>
</ul>
</li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
<li><a class="reference internal" href="#security-implications">Security Implications</a></li>
<li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a></li>
<li><a class="reference internal" href="#appendices">Appendices</a></li>
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="provisional-acceptance">
<h2><a class="toc-backref" href="#provisional-acceptance" role="doc-backlink">Provisional Acceptance</a></h2>
<p>This PEP has been <strong>provisionally accepted</strong>,
with the following required conditions before the PEP is made Final:</p>
<ol class="arabic simple">
<li>An implementation of the PEP in two build back-ends.</li>
<li>An implementation of the PEP in PyPI.</li>
</ol>
</section>
<section id="abstract">
<span id="id1"></span><h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP defines a specification how licenses are documented in the Python
projects.</p>
<p>To achieve that, it:</p>
<ul class="simple">
<li>Adopts the <a class="reference internal" href="#spdx">SPDX license expression syntax</a> as a
means of expressing the license for a Python project.</li>
<li>Defines how to include license files within the projects, source and built
distributions.</li>
<li>Specifies the necessary changes to <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Core-Metadata" title="(in Python Packaging User Guide)"><span class="xref std std-term">Core Metadata</span></a> and
the corresponding <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Pyproject-Metadata-Key" title="(in Python Packaging User Guide)"><span class="xref std std-term">Pyproject Metadata key</span></a>s</li>
<li>Describes the necessary changes to
the <a class="reference external" href="https://packaging.python.org/specifications/source-distribution-format/">source distribution (sdist)</a>,
<a class="reference external" href="https://packaging.python.org/specifications/binary-distribution-format/">built distribution (wheel)</a> and
<a class="reference external" href="https://packaging.python.org/specifications/recording-installed-packages/">installed project</a> standards.</li>
</ul>
<p>This will make license declaration simpler and less ambiguous for
package authors to create, end users to understand,
and tools to programmatically process.</p>
<p>The changes will update the
<a class="reference external" href="https://packaging.python.org/specifications/core-metadata">Core Metadata specification</a> to version 2.4.</p>
</section>
<section id="goals">
<span id="id2"></span><h2><a class="toc-backref" href="#goals" role="doc-backlink">Goals</a></h2>
<p>This PEPs scope is limited to covering new mechanisms for documenting
the license of a <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Distribution-Package" title="(in Python Packaging User Guide)"><span class="xref std std-term">distribution package</span></a>, specifically defining:</p>
<ul class="simple">
<li>A means of specifying a SPDX <a class="reference internal" href="#term-license-expression"><span class="xref std std-term">license expression</span></a>.</li>
<li>A method of including license texts in <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Distribution-Package" title="(in Python Packaging User Guide)"><span class="xref std std-term">distribution package</span></a>s
and installed <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Project" title="(in Python Packaging User Guide)"><span class="xref std std-term">Project</span></a>s.</li>
</ul>
<p>The changes that this PEP requires have been designed to minimize impact and
maximize backward compatibility.</p>
</section>
<section id="non-goals">
<span id="id3"></span><h2><a class="toc-backref" href="#non-goals" role="doc-backlink">Non-Goals</a></h2>
<p>This PEP doesnt recommend any particular license to be chosen by any
particular package author.</p>
<p>If projects decide not to use the new fields, no additional restrictions are
imposed by this PEP when uploading to PyPI.</p>
<p>This PEP also is not about license documentation for individual files,
though this is a <a class="reference internal" href="appendix-license-survey/#license-doc-source-files"><span class="std std-ref">surveyed topic</span></a>
in an appendix, nor does it intend to cover cases where the
<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist" title="(in Python Packaging User Guide)"><span class="xref std std-term">source distribution</span></a> and
<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Binary-Distribution" title="(in Python Packaging User Guide)"><span class="xref std std-term">binary distribution</span></a> packages dont have
<a class="reference internal" href="appendix-rejected-ideas/#rejected-ideas-difference-license-source-binary"><span class="std std-ref">the same licenses</span></a>.</p>
</section>
<section id="motivation">
<span id="id4"></span><h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>Software must be licensed in order for anyone other than its creator to
download, use, share and modify it.
Today, there are multiple fields where licenses
are documented in <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Core-Metadata" title="(in Python Packaging User Guide)"><span class="xref std std-term">Core Metadata</span></a>,
and there are limitations to what can be expressed in each of them.
This often leads to confusion both for package authors
and end users, including distribution re-packagers.</p>
<p>This has triggered a number of license-related discussions and issues,
including on <a class="reference external" href="https://github.com/pypa/trove-classifiers/issues/17">outdated and ambiguous PyPI classifiers</a>,
<a class="reference external" href="https://github.com/pypa/interoperability-peps/issues/46">license interoperability with other ecosystems</a>,
<a class="reference external" href="https://github.com/pypa/packaging-problems/issues/41">too many confusing license metadata options</a>,
<a class="reference external" href="https://github.com/pypa/wheel/issues/138">limited support for license files in the Wheel project</a>, and
<a class="reference external" href="https://github.com/pombredanne/spdx-pypi-pep/issues/1">the lack of precise license metadata</a>.</p>
<p>As a result, on average, Python packages tend to have more ambiguous and
missing license information than other common ecosystems. This is supported by
the <a class="reference external" href="https://clearlydefined.io/stats">statistics page</a> of the
<a class="reference external" href="https://clearlydefined.io">ClearlyDefined project</a>, an
<a class="reference external" href="https://opensource.org">Open Source Initiative</a> effort to help
improve licensing clarity of other FOSS projects, covering all packages
from PyPI, Maven, npm and Rubygems.</p>
<p>The current license classifiers could be extended to include the full range of
the SPDX identifiers while deprecating the ambiguous classifiers
(such as <code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">OSI</span> <span class="pre">Approved</span> <span class="pre">::</span> <span class="pre">BSD</span> <span class="pre">License</span></code>).</p>
<p>However, there are multiple arguments against such an approach:</p>
<ul class="simple">
<li>It requires a great effort to duplicate the SPDX license list and keep it in
sync.</li>
<li>It is a hard break in backward compatibility, forcing package authors
to update to new classifiers immediately when PyPI deprecates the old ones.</li>
<li>It only covers packages under a single license;
it doesnt 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.</li>
<li>It requires both authors and tools understand and implement the PyPI-specific
classifier system.</li>
<li>It does not provide as clear an indicator that a package
has adopted the new system, and should be treated accordingly.</li>
</ul>
</section>
<section id="rationale">
<span id="id5"></span><h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>A survey was conducted to map the existing license metadata
definitions in the <a class="reference internal" href="appendix-license-survey/#license-doc-python"><span class="std std-ref">Python ecosystem</span></a> and a
<a class="reference internal" href="appendix-license-survey/#license-doc-other-projects"><span class="std std-ref">variety of other packaging systems, Linux distributions,
language ecosystems and applications</span></a>.</p>
<p>The takeaways from the survey have guided the recommendations of this PEP:</p>
<ul class="simple">
<li>SPDX and SPDX-like syntaxes are the most popular <a class="reference internal" href="#term-license-expression"><span class="xref std std-term">license expression</span></a>s
in many modern package systems.</li>
<li>Most Free and Open Source Software licenses require package authors to
include their full text in a <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Distribution-Package" title="(in Python Packaging User Guide)"><span class="xref std std-term">Distribution Package</span></a>.</li>
</ul>
<p>Therefore, this PEP introduces two new Core Metadata fields:</p>
<ul class="simple">
<li><a class="reference internal" href="#spec-field-license-expression"><span class="std std-ref">License-Expression</span></a> that
provides an unambiguous way to express the license of a package
using SPDX license expressions.</li>
<li><a class="reference internal" href="#spec-field-license-file"><span class="std std-ref">License-File</span></a> that
offers a standardized way to include the full text of the license(s)
with the package when distributed,
and allows other tools consuming the <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Core-Metadata" title="(in Python Packaging User Guide)"><span class="xref std std-term">Core Metadata</span></a>
to locate a <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Distribution-Archive" title="(in Python Packaging User Guide)"><span class="xref std std-term">distribution archive</span></a>s license files.</li>
</ul>
<p>Furthermore, this specification builds upon
existing practice in the <a class="reference external" href="https://github.com/pypa/setuptools/issues/2739">Setuptools</a> and
<a class="reference external" href="https://github.com/pypa/wheel/issues/138">Wheel</a> projects.
An up-to-date version of the current draft of this PEP is
<a class="reference external" href="https://discuss.python.org/t/12622/22">implemented</a> in the
<a class="reference external" href="https://hatch.pypa.io/latest/">Hatch</a> packaging tool, and an earlier draft of the
<a class="reference internal" href="#spec-field-license-file"><span class="std std-ref">license files portion</span></a>
is <a class="reference external" href="https://github.com/pypa/setuptools/pull/2645">implemented in Setuptools</a>.</p>
</section>
<section id="terminology">
<span id="id6"></span><h2><a class="toc-backref" href="#terminology" role="doc-backlink">Terminology</a></h2>
<p>The keywords “MUST”, “MUST NOT”, “REQUIRED”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL”
in this document are to be interpreted as described in <span class="target" id="index-0"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2119.html"><strong>RFC 2119</strong></a>.</p>
<section id="license-terms">
<span id="terminology-license"></span><h3><a class="toc-backref" href="#license-terms" role="doc-backlink">License terms</a></h3>
<p>The license-related terminology draws heavily from the <a class="reference external" href="https://spdx.dev/">SPDX Project</a>,
particularly <a class="reference internal" href="#term-license-identifier"><span class="xref std std-term">license identifier</span></a> and <a class="reference internal" href="#term-license-expression"><span class="xref std std-term">license expression</span></a>.</p>
<dl class="simple glossary">
<dt id="term-license-classifier">license classifier</dt><dd>A <a class="reference external" href="https://pypi.org/classifiers">PyPI Trove classifier</a>
(as <a class="reference external" href="https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata-classifier" title="(in Python Packaging User Guide)"><span class="xref std std-ref">described</span></a>
in the <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Core-Metadata" title="(in Python Packaging User Guide)"><span class="xref std std-term">Core Metadata</span></a> specification)
which begins with <code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span></code>.</dd>
<dt id="term-license-expression">license expression</dt><dt id="term-SPDX-expression">SPDX expression</dt><dd>A string with valid <a class="reference external" href="https://spdx.github.io/spdx-spec/v2.2.2/SPDX-license-expressions/">SPDX license expression syntax</a>
including one or more SPDX <a class="reference internal" href="#term-license-identifier"><span class="xref std std-term">license identifier</span></a>(s),
which describes a <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Project" title="(in Python Packaging User Guide)"><span class="xref std std-term">Project</span></a>s license(s)
and how they inter-relate.
Examples:
<code class="docutils literal notranslate"><span class="pre">GPL-3.0-or-later</span></code>,
<code class="docutils literal notranslate"><span class="pre">MIT</span> <span class="pre">AND</span> <span class="pre">(Apache-2.0</span> <span class="pre">OR</span> <span class="pre">BSD-2-clause)</span></code></dd>
<dt id="term-license-identifier">license identifier</dt><dt id="term-SPDX-identifier">SPDX identifier</dt><dd>A valid <a class="reference external" href="https://spdx.dev/ids/">SPDX short-form license identifier</a>,
as described in the
<a class="reference internal" href="#spec-field-license-expression"><span class="std std-ref">Add License-Expression field</span></a> section of this PEP.
This includes all valid SPDX identifiers and
the custom <code class="docutils literal notranslate"><span class="pre">LicenseRef-[idstring]</span></code> strings conforming to the
<a class="reference external" href="https://spdx.github.io/spdx-spec/v2.2.2/other-licensing-information-detected/">SPDX specification, clause 10.1</a>.
Examples:
<code class="docutils literal notranslate"><span class="pre">MIT</span></code>,
<code class="docutils literal notranslate"><span class="pre">GPL-3.0-only</span></code>,
<code class="docutils literal notranslate"><span class="pre">LicenseRef-My-Custom-License</span></code></dd>
<dt id="term-root-license-directory">root license directory</dt><dt id="term-license-directory">license directory</dt><dd>The directory under which license files are stored in a
<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Project-Source-Tree" title="(in Python Packaging User Guide)"><span class="xref std std-term">project source tree</span></a>, <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Distribution-Archive" title="(in Python Packaging User Guide)"><span class="xref std std-term">distribution archive</span></a>
or <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Installed-Project" title="(in Python Packaging User Guide)"><span class="xref std std-term">installed project</span></a>.
Also, the root directory that their paths
recorded in the <a class="reference internal" href="#spec-field-license-file"><span class="std std-ref">License-File</span></a>
<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Core-Metadata-Field" title="(in Python Packaging User Guide)"><span class="xref std std-term">Core Metadata field</span></a> are relative to.
Defined to be the <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Project-Root-Directory" title="(in Python Packaging User Guide)"><span class="xref std std-term">project root directory</span></a>
for a <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Project-Source-Tree" title="(in Python Packaging User Guide)"><span class="xref std std-term">project source tree</span></a> or
<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist" title="(in Python Packaging User Guide)"><span class="xref std std-term">source distribution</span></a>;
and a subdirectory named <code class="docutils literal notranslate"><span class="pre">licenses</span></code> of
the directory containing the <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Built-Metadata" title="(in Python Packaging User Guide)"><span class="xref std std-term">built metadata</span></a>
i.e., the <code class="docutils literal notranslate"><span class="pre">.dist-info/licenses</span></code> directory—
for a <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Built-Distribution" title="(in Python Packaging User Guide)"><span class="xref std std-term">Built Distribution</span></a> or <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Installed-Project" title="(in Python Packaging User Guide)"><span class="xref std std-term">installed project</span></a>.</dd>
</dl>
</section>
</section>
<section id="specification">
<span id="id7"></span><h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<p>The changes necessary to implement this PEP include:</p>
<ul class="simple">
<li>additions to <a class="reference internal" href="#spec-core-metadata"><span class="std std-ref">Core Metadata</span></a>,
as defined in the <a class="reference external" href="https://packaging.python.org/specifications/core-metadata">specification</a>.</li>
<li>additions to the author-provided
<a class="reference internal" href="#spec-source-metadata"><span class="std std-ref">project source metadata</span></a>,
as defined in the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/pyproject-toml/">specification</a>.</li>
<li><a class="reference internal" href="#spec-project-formats"><span class="std std-ref">additions</span></a> to the
source distribution (sdist), built distribution (wheel) and installed project
specifications.</li>
<li><a class="reference internal" href="#spec-converting-metadata"><span class="std std-ref">guide for tools</span></a>
handling and converting legacy license metadata to license
expressions, to ensure the results are consistent and correct.</li>
</ul>
<p>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.</p>
<section id="spdx-license-expression-syntax">
<span id="spdx"></span><h3><a class="toc-backref" href="#spdx-license-expression-syntax" role="doc-backlink">SPDX license expression syntax</a></h3>
<p>This PEP adopts the SPDX license expression syntax as
documented in the <a class="reference external" href="https://spdx.github.io/spdx-spec/v2.2.2/SPDX-license-expressions/">SPDX specification</a>, either
Version 2.2 or a later compatible version.</p>
<p>A license expression can use the following <a class="reference internal" href="#term-license-identifier"><span class="xref std std-term">license identifier</span></a>s:</p>
<ul class="simple">
<li>Any SPDX-listed license short-form identifiers that are published in the
<a class="reference external" href="https://spdx.org/licenses/">SPDX License List</a>, version 3.17 or any later compatible
version. Note that the SPDX working group never removes any license
identifiers; instead, they may choose to mark an identifier as “deprecated”.</li>
<li>The custom <code class="docutils literal notranslate"><span class="pre">LicenseRef-[idstring]</span></code> string(s), where
<code class="docutils literal notranslate"><span class="pre">[idstring]</span></code> is a unique string containing letters, numbers,
<code class="docutils literal notranslate"><span class="pre">.</span></code> and/or <code class="docutils literal notranslate"><span class="pre">-</span></code>, to identify licenses that are not included in the SPDX
license list. The custom identifiers must follow the SPDX specification,
<a class="reference external" href="https://spdx.github.io/spdx-spec/v2.2.2/other-licensing-information-detected/">clause 10.1</a> of the given specification version.</li>
</ul>
<p>Examples of valid SPDX expressions:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>MIT
BSD-3-Clause
MIT 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-Clause
LicenseRef-Special-License OR CC0-1.0 OR Unlicense
LicenseRef-Proprietary
</pre></div>
</div>
<p>Examples of invalid SPDX expressions:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Use-it-after-midnight
Apache-2.0 OR 2-BSD-Clause
LicenseRef-License with spaces
LicenseRef-License_with_underscores
</pre></div>
</div>
</section>
<section id="core-metadata">
<span id="spec-core-metadata"></span><h3><a class="toc-backref" href="#core-metadata" role="doc-backlink">Core Metadata</a></h3>
<p>The error and warning guidance in this section applies to build and
publishing tools; end-user-facing install tools MAY be less strict than
mentioned here when encountering malformed metadata
that does not conform to this specification.</p>
<p>As it adds new fields, this PEP updates the Core Metadata version to 2.4.</p>
<section id="add-license-expression-field">
<span id="spec-field-license-expression"></span><h4><a class="toc-backref" href="#add-license-expression-field" role="doc-backlink">Add <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field</a></h4>
<p>The <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> optional <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Core-Metadata-Field" title="(in Python Packaging User Guide)"><span class="xref std std-term">Core Metadata field</span></a>
is specified to contain a text string
that is a valid SPDX <a class="reference internal" href="#term-license-expression"><span class="xref std std-term">license expression</span></a>,
as <a class="reference internal" href="#spdx"><span class="std std-ref">defined above</span></a>.</p>
<p>Build and publishing tools SHOULD
check that the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field contains a valid SPDX expression,
including the validity of the particular license identifiers
(as <a class="reference internal" href="#spdx"><span class="std std-ref">defined above</span></a>).
Tools MAY halt execution and raise an error when an invalid expression is found.
If tools choose to validate the SPDX expression, they also SHOULD
store a case-normalized version of the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code>
field using the reference case for each SPDX license identifier and uppercase
for the <code class="docutils literal notranslate"><span class="pre">AND</span></code>, <code class="docutils literal notranslate"><span class="pre">OR</span></code> and <code class="docutils literal notranslate"><span class="pre">WITH</span></code> keywords.
Tools SHOULD report a warning and publishing tools MAY raise an error
if one or more license identifiers
have been marked as deprecated in the <a class="reference external" href="https://spdx.org/licenses/">SPDX License List</a>.</p>
<p>For all newly-uploaded <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Distribution-Archive" title="(in Python Packaging User Guide)"><span class="xref std std-term">distribution archive</span></a>s
that include a <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field,
the <a class="reference external" href="https://pypi.org/">Python Package Index (PyPI)</a> MUST
validate that they contain a valid, case-normalized license expression with
valid identifiers (as <a class="reference internal" href="#spdx"><span class="std std-ref">defined above</span></a>)
and MUST reject uploads that do not.
Custom license identifiers which conform to the SPDX specification
are 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 List
version.</p>
</section>
<section id="add-license-file-field">
<span id="spec-field-license-file"></span><h4><a class="toc-backref" href="#add-license-file-field" role="doc-backlink">Add <code class="docutils literal notranslate"><span class="pre">License-File</span></code> field</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">License-File</span></code> is an optional <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Core-Metadata-Field" title="(in Python Packaging User Guide)"><span class="xref std std-term">Core Metadata field</span></a>.
Each instance contains the string
representation of the path of a license-related file. The path is located
within the <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Project-Source-Tree" title="(in Python Packaging User Guide)"><span class="xref std std-term">project source tree</span></a>, relative to the
<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Project-Root-Directory" title="(in Python Packaging User Guide)"><span class="xref std std-term">project root directory</span></a>.
It is a multi-use field that may appear zero or
more times and each instance lists the path to one such file. Files specified
under this field could include license text, author/attribution information,
or other legal notices that need to be distributed with the package.</p>
<p>As <a class="reference internal" href="#spec-project-formats"><span class="std std-ref">specified by this PEP</span></a>, its value
is also that files path relative to the <a class="reference internal" href="#term-root-license-directory"><span class="xref std std-term">root license directory</span></a>
in both <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Installed-Project" title="(in Python Packaging User Guide)"><span class="xref std std-term">installed project</span></a>s
and the standardized <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Distribution-Package" title="(in Python Packaging User Guide)"><span class="xref std std-term">Distribution Package</span></a> types.</p>
<p>If a <code class="docutils literal notranslate"><span class="pre">License-File</span></code> is listed in a
<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist" title="(in Python Packaging User Guide)"><span class="xref std std-term">Source Distribution</span></a> or
<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Built-Distribution" title="(in Python Packaging User Guide)"><span class="xref std std-term">Built Distribution</span></a>s Core Metadata:</p>
<ul class="simple">
<li>That file MUST be included in the <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Distribution-Archive" title="(in Python Packaging User Guide)"><span class="xref std std-term">distribution archive</span></a> at the
specified path relative to the root license directory.</li>
<li>That file MUST be installed with the <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Project" title="(in Python Packaging User Guide)"><span class="xref std std-term">project</span></a> at that same relative
path.</li>
<li>The specified relative path MUST be consistent between project source trees,
source distributions (sdists), built distributions (<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Wheel" title="(in Python Packaging User Guide)"><span class="xref std std-term">Wheel</span></a>s) and
installed projects.</li>
<li>Inside the root license directory, packaging tools MUST reproduce the
directory structure under which the source license files are located
relative to the project root.</li>
<li>Path delimiters MUST be the forward slash character (<code class="docutils literal notranslate"><span class="pre">/</span></code>),
and parent directory indicators (<code class="docutils literal notranslate"><span class="pre">..</span></code>) MUST NOT be used.</li>
<li>License file content MUST be UTF-8 encoded text.</li>
</ul>
<p>Build tools MAY and publishing tools SHOULD produce an informative warning
if a built distributions metadata contains no <code class="docutils literal notranslate"><span class="pre">License-File</span></code> entries,
and publishing tools MAY but build tools MUST NOT raise an error.</p>
<p>For all newly-uploaded <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Distribution-Archive" title="(in Python Packaging User Guide)"><span class="xref std std-term">distribution archive</span></a>s that include one or more
<code class="docutils literal notranslate"><span class="pre">License-File</span></code> fields in their Core Metadata
and declare a <code class="docutils literal notranslate"><span class="pre">Metadata-Version</span></code> of <code class="docutils literal notranslate"><span class="pre">2.4</span></code> or higher,
PyPI SHOULD validate that all specified files are present in that
<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Distribution-Archive" title="(in Python Packaging User Guide)"><span class="xref std std-term">distribution archive</span></a>s,
and MUST reject uploads that do not validate.</p>
</section>
<section id="deprecate-license-field">
<span id="spec-field-license"></span><h4><a class="toc-backref" href="#deprecate-license-field" role="doc-backlink">Deprecate <code class="docutils literal notranslate"><span class="pre">License</span></code> field</a></h4>
<p>The legacy unstructured-text <code class="docutils literal notranslate"><span class="pre">License</span></code> <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Core-Metadata-Field" title="(in Python Packaging User Guide)"><span class="xref std std-term">Core Metadata field</span></a>
is deprecated and replaced by the new <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> 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 present
at the same time, MUST read the value of <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> and MUST
disregard the value of the <code class="docutils literal notranslate"><span class="pre">License</span></code> field.</p>
<p>If only the <code class="docutils literal notranslate"><span class="pre">License</span></code> field is present, tools MAY issue a warning
informing users it is deprecated and recommending <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code>
instead.</p>
<p>For all newly-uploaded <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Distribution-Archive" title="(in Python Packaging User Guide)"><span class="xref std std-term">distribution archive</span></a>s that include a
<code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field, the <a class="reference external" href="https://pypi.org/">Python Package Index (PyPI)</a> MUST
reject any that specify both <code class="docutils literal notranslate"><span class="pre">License</span></code> and <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> fields.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">License</span></code> field may be removed from a new version of the specification
in a future PEP.</p>
</section>
<section id="deprecate-license-classifiers">
<span id="spec-field-classifier"></span><h4><a class="toc-backref" href="#deprecate-license-classifiers" role="doc-backlink">Deprecate license classifiers</a></h4>
<p>Using <a class="reference internal" href="#term-license-classifier"><span class="xref std std-term">license classifier</span></a>s
in the <code class="docutils literal notranslate"><span class="pre">Classifier</span></code> <a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Core-Metadata-Field" title="(in Python Packaging User Guide)"><span class="xref std std-term">Core Metadata field</span></a>
(<a class="reference external" href="https://packaging.python.org/en/latest/specifications/core-metadata/#classifier-multiple-use">described in the Core Metadata specification</a>)
is deprecated and replaced by the more precise <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field.</p>
<p>If the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field is present, build tools MAY raise an error
if one or more license classifiers
is included in a <code class="docutils literal notranslate"><span class="pre">Classifier</span></code> field, and MUST NOT add
such classifiers themselves.</p>
<p>Otherwise, if this field contains a license classifier,
tools MAY issue a warning informing users such classifiers
are deprecated, and recommending <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> instead.
For compatibility with existing publishing and installation processes,
the presence of license classifiers SHOULD NOT raise an error unless
<code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> is also provided.</p>
<p>New license classifiers MUST NOT be <a class="reference external" href="https://github.com/pypa/trove-classifiers">added to PyPI</a>;
users needing them SHOULD use the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field instead.
License classifiers may be removed from a new version of the specification
in a future PEP.</p>
</section>
</section>
<section id="project-source-metadata">
<span id="spec-source-metadata"></span><h3><a class="toc-backref" href="#project-source-metadata" role="doc-backlink">Project source metadata</a></h3>
<p>This PEP specifies changes to the projects source
metadata under a <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table in the <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> file.</p>
<section id="add-string-value-to-license-key">
<span id="spec-key-license-text"></span><h4><a class="toc-backref" href="#add-string-value-to-license-key" role="doc-backlink">Add string value to <code class="docutils literal notranslate"><span class="pre">license</span></code> key</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">license</span></code> key in the <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table is defined to contain a top-level
string value. It is a valid SPDX license expression as
<a class="reference internal" href="#spdx"><span class="std std-ref">defined in this PEP</span></a>.
Its value maps to the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field in the core metadata.</p>
<p>Build tools SHOULD validate and perform case normalization of the expression
as described in the
<a class="reference internal" href="#spec-field-license-expression"><span class="std std-ref">Add License-Expression field</span></a> section,
outputting an error or warning as specified.</p>
<p>Examples:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[project]</span>
<span class="n">license</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;MIT&quot;</span>
<span class="k">[project]</span>
<span class="n">license</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;MIT AND (Apache-2.0 OR BSD-2-clause)&quot;</span>
<span class="k">[project]</span>
<span class="n">license</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;MIT OR GPL-2.0-or-later OR (FSFUL AND BSD-2-Clause)&quot;</span>
<span class="k">[project]</span>
<span class="n">license</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;LicenseRef-Proprietary&quot;</span>
</pre></div>
</div>
</section>
<section id="add-license-files-key">
<span id="spec-key-license-files"></span><h4><a class="toc-backref" href="#add-license-files-key" role="doc-backlink">Add <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key</a></h4>
<p>A new <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key is added to the <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table for specifying
paths in the project source tree relative to <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> to file(s)
containing licenses and other legal notices to be distributed with the package.
It corresponds to the <code class="docutils literal notranslate"><span class="pre">License-File</span></code> fields in the Core Metadata.</p>
<p>Its value is an array of strings which MUST contain valid glob patterns,
as specified below:</p>
<ul class="simple">
<li>Alphanumeric characters, underscores (<code class="docutils literal notranslate"><span class="pre">_</span></code>), hyphens (<code class="docutils literal notranslate"><span class="pre">-</span></code>) and dots (<code class="docutils literal notranslate"><span class="pre">.</span></code>)
MUST be matched verbatim.</li>
<li>Special glob characters: <code class="docutils literal notranslate"><span class="pre">*</span></code>, <code class="docutils literal notranslate"><span class="pre">?</span></code>, <code class="docutils literal notranslate"><span class="pre">**</span></code> and character ranges: <code class="docutils literal notranslate"><span class="pre">[]</span></code>
containing only the verbatim matched characters MUST be supported.
Within <code class="docutils literal notranslate"><span class="pre">[...]</span></code>, the hyphen indicates a locale-agnostic range (e.g. <code class="docutils literal notranslate"><span class="pre">a-z</span></code>,
order based on Unicode code points).
Hyphens at the start or end are matched literally.</li>
<li>Path delimiters MUST be the forward slash character (<code class="docutils literal notranslate"><span class="pre">/</span></code>).
Patterns are relative to the directory containing <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>,
therefore the leading slash character MUST NOT be used.</li>
<li>Parent directory indicators (<code class="docutils literal notranslate"><span class="pre">..</span></code>) MUST NOT be used.</li>
</ul>
<p>Any characters or character sequences not covered by this specification are
invalid. Projects MUST NOT use such values.
Tools consuming this field SHOULD reject invalid values with an error.</p>
<p>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.</p>
<p>Literal paths (e.g. <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code>) are treated as valid globs which means they
can also be defined.</p>
<p>Build tools:</p>
<ul class="simple">
<li>MUST treat each value as a glob pattern, and MUST raise an error if the
pattern contains invalid glob syntax.</li>
<li>MUST include all files matched by a listed pattern in all
distribution archives.</li>
<li>MUST list each matched file path under a <code class="docutils literal notranslate"><span class="pre">License-File</span></code> field in the
Core Metadata.</li>
<li>MUST raise an error if any individual user-specified pattern
does not match at least one file.</li>
</ul>
<p>If the <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key is present and
is set to a value of an empty array, then tools MUST NOT include any
license files and MUST NOT raise an error.</p>
<p>Examples of valid license files declaration:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[project]</span>
<span class="n">license-files</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;LICEN[CS]E*&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;AUTHORS*&quot;</span><span class="p">]</span>
<span class="k">[project]</span>
<span class="n">license-files</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;licenses/LICENSE.MIT&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;licenses/LICENSE.CC0&quot;</span><span class="p">]</span>
<span class="k">[project]</span>
<span class="n">license-files</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;LICENSE.txt&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;licenses/*&quot;</span><span class="p">]</span>
<span class="k">[project]</span>
<span class="n">license-files</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[]</span>
</pre></div>
</div>
<p>Examples of invalid license files declaration:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[project]</span>
<span class="n">license-files</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;..</span><span class="se">\L</span><span class="s2">ICENSE.MIT&quot;</span><span class="p">]</span>
</pre></div>
</div>
<p>Reason: <code class="docutils literal notranslate"><span class="pre">..</span></code> must not be used.
<code class="docutils literal notranslate"><span class="pre">\</span></code> is an invalid path delimiter, <code class="docutils literal notranslate"><span class="pre">/</span></code> must be used.</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[project]</span>
<span class="n">license-files</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;LICEN{CSE*&quot;</span><span class="p">]</span>
</pre></div>
</div>
<p>Reason: “LICEN{CSE*” is not a valid glob.</p>
</section>
<section id="deprecate-license-key-table-subkeys">
<span id="spec-key-license-table"></span><h4><a class="toc-backref" href="#deprecate-license-key-table-subkeys" role="doc-backlink">Deprecate <code class="docutils literal notranslate"><span class="pre">license</span></code> key table subkeys</a></h4>
<p>Table values for the <code class="docutils literal notranslate"><span class="pre">license</span></code> key in the <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table,
including the <code class="docutils literal notranslate"><span class="pre">text</span></code> and <code class="docutils literal notranslate"><span class="pre">file</span></code> table subkeys, are now deprecated.
If the new <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key is present,
build tools MUST raise an error if the <code class="docutils literal notranslate"><span class="pre">license</span></code> key is defined
and has a value other than a single top-level string.</p>
<p>If the new <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key is not present
and the <code class="docutils literal notranslate"><span class="pre">text</span></code> subkey is present in a <code class="docutils literal notranslate"><span class="pre">license</span></code> table,
tools SHOULD issue a warning informing users it is deprecated
and recommending a license expression as a top-level string key instead.</p>
<p>Likewise, if the new <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key is not present
and the <code class="docutils literal notranslate"><span class="pre">file</span></code> subkey is present in the <code class="docutils literal notranslate"><span class="pre">license</span></code> table,
tools SHOULD issue a warning informing users it is deprecated and recommending
the <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key instead.</p>
<p>If the specified license <code class="docutils literal notranslate"><span class="pre">file</span></code> is present in the source tree,
build tools SHOULD use it to fill the <code class="docutils literal notranslate"><span class="pre">License-File</span></code> field
in the core metadata, and MUST include the specified file
as if it were specified in a <code class="docutils literal notranslate"><span class="pre">license-file</span></code> field.
If the file does not exist at the specified path,
tools MUST raise an informative error as previously specified.</p>
<p>Table values for the <code class="docutils literal notranslate"><span class="pre">license</span></code> key MAY be removed
from a new version of the specification in a future PEP.</p>
</section>
</section>
<section id="license-files-in-project-formats">
<span id="spec-project-formats"></span><h3><a class="toc-backref" href="#license-files-in-project-formats" role="doc-backlink">License files in project formats</a></h3>
<p>A few additions will be made to the existing specifications.</p>
<dl class="simple">
<dt><a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Project-Source-Tree" title="(in Python Packaging User Guide)"><span class="xref std std-term">Project source tree</span></a>s</dt><dd>Per <a class="reference internal" href="#spec-source-metadata"><span class="std std-ref">Project source metadata</span></a> section, the
<a class="reference external" href="https://packaging.python.org/en/latest/specifications/pyproject-toml/">Declaring Project Metadata specification</a>
will be updated to reflect that license file paths MUST be relative to the
project root directory; i.e. the directory containing the <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>
(or equivalently, other legacy project configuration,
e.g. <code class="docutils literal notranslate"><span class="pre">setup.py</span></code>, <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code>, etc).</dd>
<dt><a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist" title="(in Python Packaging User Guide)"><span class="xref std std-term">Source distributions (sdists)</span></a></dt><dd>The <a class="reference external" href="https://packaging.python.org/specifications/source-distribution-format/">sdist specification</a> will be updated to reflect that if
the <code class="docutils literal notranslate"><span class="pre">Metadata-Version</span></code> is <code class="docutils literal notranslate"><span class="pre">2.4</span></code> or greater,
the sdist MUST contain any license files specified by
the <a class="reference internal" href="#spec-field-license-file"><span class="std std-ref">License-File field</span></a>
in the <code class="docutils literal notranslate"><span class="pre">PKG-INFO</span></code> at their respective paths
relative to the of the sdist
(containing the <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> and the <code class="docutils literal notranslate"><span class="pre">PKG-INFO</span></code> Core Metadata).</dd>
<dt><a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Built-Distribution" title="(in Python Packaging User Guide)"><span class="xref std std-term">Built distribution</span></a>s (<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Wheel" title="(in Python Packaging User Guide)"><span class="xref std std-term">wheel</span></a>s)</dt><dd>The <a class="reference external" href="https://packaging.python.org/specifications/binary-distribution-format/">Wheel specification</a> will be updated to reflect that if
the <code class="docutils literal notranslate"><span class="pre">Metadata-Version</span></code> is <code class="docutils literal notranslate"><span class="pre">2.4</span></code> or greater and one or more
<code class="docutils literal notranslate"><span class="pre">License-File</span></code> fields is specified, the <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directory MUST
contain a <code class="docutils literal notranslate"><span class="pre">licenses</span></code> subdirectory, which MUST contain the files listed
in the <code class="docutils literal notranslate"><span class="pre">License-File</span></code> fields in the <code class="docutils literal notranslate"><span class="pre">METADATA</span></code> file at their respective
paths relative to the <code class="docutils literal notranslate"><span class="pre">licenses</span></code> directory.</dd>
<dt><a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Installed-Project" title="(in Python Packaging User Guide)"><span class="xref std std-term">Installed project</span></a>s</dt><dd>The <a class="reference external" href="https://packaging.python.org/specifications/recording-installed-packages/">Recording Installed Projects specification</a> will be
updated to reflect that if the <code class="docutils literal notranslate"><span class="pre">Metadata-Version</span></code> is <code class="docutils literal notranslate"><span class="pre">2.4</span></code> or greater
and one or more <code class="docutils literal notranslate"><span class="pre">License-File</span></code> fields is specified, the <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code>
directory MUST contain a <code class="docutils literal notranslate"><span class="pre">licenses</span></code> subdirectory which MUST contain
the files listed in the <code class="docutils literal notranslate"><span class="pre">License-File</span></code> fields in the <code class="docutils literal notranslate"><span class="pre">METADATA</span></code> file
at their respective paths relative to the <code class="docutils literal notranslate"><span class="pre">licenses</span></code> directory,
and that any files in this directory MUST be copied from wheels
by install tools.</dd>
</dl>
</section>
<section id="converting-legacy-metadata">
<span id="spec-converting-metadata"></span><h3><a class="toc-backref" href="#converting-legacy-metadata" role="doc-backlink">Converting legacy metadata</a></h3>
<p>Tools MUST NOT use the contents of the <code class="docutils literal notranslate"><span class="pre">license.text</span></code> <code class="docutils literal notranslate"><span class="pre">[project]</span></code> key
(or equivalent tool-specific format),
license classifiers or the value of the Core Metadata <code class="docutils literal notranslate"><span class="pre">License</span></code> field
to fill the top-level string value of the <code class="docutils literal notranslate"><span class="pre">license</span></code> key
or the Core Metadata <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field
without informing the user and requiring unambiguous, affirmative user action
to select and confirm the desired license expression value before proceeding.</p>
<p>Tool authors, who need to automatically convert license classifiers to
SPDX identifiers, can use the
<a class="reference internal" href="appendix-mapping-classifiers/#spec-mapping-classifiers-identifiers"><span class="std std-ref">recommendation</span></a> prepared by
the PEP authors.</p>
</section>
</section>
<section id="backwards-compatibility">
<span id="id8"></span><h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2>
<p>Adding a new <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> Core Metadata field and a top-level string
value for the <code class="docutils literal notranslate"><span class="pre">license</span></code> key in the <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table
unambiguously means support for the specification in this PEP. This avoids the
risk of new tooling misinterpreting a license expression as a free-form license
description or vice versa.</p>
<p>The legacy deprecated Core Metadata <code class="docutils literal notranslate"><span class="pre">License</span></code> field, <code class="docutils literal notranslate"><span class="pre">license</span></code> key table
subkeys (<code class="docutils literal notranslate"><span class="pre">text</span></code> and <code class="docutils literal notranslate"><span class="pre">file</span></code>) in the <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table
and license classifiers retain backwards compatibility. A removal is
left to a future PEP and a new version of the Core Metadata specification.</p>
<p>Specification of the new <code class="docutils literal notranslate"><span class="pre">License-File</span></code> Core Metadata field and adding the
files in the distribution is designed to be largely backwards-compatible with
the existing use of that field in many packaging tools.
The new <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key in the <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table of
<code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> will only have an effect once users and tools adopt it.</p>
<p>This PEP specifies that license files should be placed in a dedicated
<code class="docutils literal notranslate"><span class="pre">licenses</span></code> subdir of <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directory. This is new and ensures that
wheels following this PEP will have differently-located licenses relative to
those produced via the previous installer-specific behavior. This is further
supported by a new metadata version.</p>
<p>This also resolves current issues where license files are accidentally
replaced if they have the same names in different places, making wheels
undistributable without noticing. It also prevents conflicts with other
metadata files in the same directory.</p>
<p>The additions will be made to the source distribution (sdist), built
distribution (wheel) and installed project specifications. They document
behaviors allowed under their current specifications, and gate them behind the
new metadata version.</p>
<p>This PEP proposes PyPI implement validation of the new
<code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> and <code class="docutils literal notranslate"><span class="pre">License-File</span></code> fields, which has no effect on
new and existing packages uploaded unless they explicitly opt in to using
these new fields and fail to follow the specification correctly.
Therefore, this does not have a backward compatibility impact, and guarantees
forward compatibility by ensuring all distributions uploaded to PyPI with the
new fields conform to the specification.</p>
</section>
<section id="security-implications">
<span id="id9"></span><h2><a class="toc-backref" href="#security-implications" role="doc-backlink">Security Implications</a></h2>
<p>This PEP has no foreseen security implications: the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code>
field is a plain string and the <code class="docutils literal notranslate"><span class="pre">License-File</span></code> fields are file paths.
Neither introduces any known new security concerns.</p>
</section>
<section id="how-to-teach-this">
<span id="id10"></span><h2><a class="toc-backref" href="#how-to-teach-this" role="doc-backlink">How to Teach This</a></h2>
<p>A majority of packages use a single license which makes the case simple:
a single license identifier is a valid license expression.</p>
<p>Users of packaging tools will learn the valid license expression of their
package through the messages issued by the tools when they detect invalid
ones, or when the deprecated <code class="docutils literal notranslate"><span class="pre">License</span></code> field or license classifiers are used.</p>
<p>If an invalid <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> is used, the users will not be able
to publish their package to PyPI and an error message will help them
understand 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 enforces
<code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> validity.
For authors using the now-deprecated <code class="docutils literal notranslate"><span class="pre">License</span></code> field or license classifiers,
packaging tools may warn them and inform them of the replacement,
<code class="docutils literal notranslate"><span class="pre">License-Expression</span></code>.</p>
<p>Tools may also help with the conversion and suggest a license expression in
many common cases:</p>
<ul class="simple">
<li>The appendix <a class="reference internal" href="appendix-mapping-classifiers/#spec-mapping-classifiers-identifiers"><span class="std std-ref">Appendix: Mapping License Classifiers to SPDX Identifiers</span></a> provides
tool authors with recommendation on how to suggest a license expression
produced from legacy classifiers.</li>
<li>Tools may be able to suggest how to update an existing <code class="docutils literal notranslate"><span class="pre">License</span></code> value
in project source metadata and convert that to a license expression,
as also <a class="reference internal" href="#spec-converting-metadata"><span class="std std-ref">specified in this PEP</span></a>.</li>
</ul>
</section>
<section id="reference-implementation">
<span id="id11"></span><h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>Tools will need to support parsing and validating license expressions in the
<code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field if they decide to implement this part of the
specification.
Its up to the tools whether they prefer to implement the validation on their
side (e.g. like <a class="reference external" href="https://github.com/pypa/hatch/blob/hatchling-v1.24.2/backend/src/hatchling/licenses/parse.py#L8-L18">hatch</a>) or use one of the available
Python libraries (e.g. <a class="reference external" href="https://github.com/nexB/license-expression/">license-expression</a>).
This PEP does not mandate using any specific library and leaves it to the
tools authors to choose the best implementation for their projects.</p>
</section>
<section id="rejected-ideas">
<span id="id12"></span><h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2>
<p>Many alternative ideas were proposed and after a careful consideration,
rejected. The exhaustive list including the rationale for rejecting can be found
in a <a class="reference internal" href="appendix-rejected-ideas/#rejected-ideas-details"><span class="std std-ref">separate page</span></a>.</p>
</section>
<section id="appendices">
<h2><a class="toc-backref" href="#appendices" role="doc-backlink">Appendices</a></h2>
<p>A list of auxiliary documents is provided:</p>
<ul class="simple">
<li>Detailed <a class="reference internal" href="appendix-examples/#examples"><span class="std std-ref">Licensing Examples</span></a>,</li>
<li><a class="reference internal" href="appendix-user-scenarios/#user-scenarios"><span class="std std-ref">User Scenarios</span></a>,</li>
<li><a class="reference internal" href="appendix-license-survey/#license-doc-python"><span class="std std-ref">License Documentation in Python and Other Projects</span></a>,</li>
<li><a class="reference internal" href="appendix-mapping-classifiers/#spec-mapping-classifiers-identifiers"><span class="std std-ref">Mapping License Classifiers to SPDX Identifiers</span></a>,</li>
<li><a class="reference internal" href="appendix-rejected-ideas/#rejected-ideas-details"><span class="std std-ref">Rejected Ideas</span></a> in detail.</li>
</ul>
</section>
<section id="acknowledgments">
<h2><a class="toc-backref" href="#acknowledgments" role="doc-backlink">Acknowledgments</a></h2>
<ul class="simple">
<li>Alyssa Coghlan</li>
<li>Kevin P. Fleming</li>
<li>Pradyun Gedam</li>
<li>Oleg Grenrus</li>
<li>Dustin Ingram</li>
<li>Chris Jerdonek</li>
<li>Cyril Roelandt</li>
<li>Luis Villa</li>
<li>Seth M. Larson</li>
<li>Ofek Lev</li>
</ul>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document is placed in the public domain or under the
<a class="reference external" href="https://creativecommons.org/publicdomain/zero/1.0/">CC0-1.0-Universal license</a>, whichever is more permissive.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0639.rst">https://github.com/python/peps/blob/main/peps/pep-0639.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0639.rst">2024-08-29 18:30:14 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#provisional-acceptance">Provisional Acceptance</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#goals">Goals</a></li>
<li><a class="reference internal" href="#non-goals">Non-Goals</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#terminology">Terminology</a><ul>
<li><a class="reference internal" href="#license-terms">License terms</a></li>
</ul>
</li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#spdx-license-expression-syntax">SPDX license expression syntax</a></li>
<li><a class="reference internal" href="#core-metadata">Core Metadata</a><ul>
<li><a class="reference internal" href="#add-license-expression-field">Add <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field</a></li>
<li><a class="reference internal" href="#add-license-file-field">Add <code class="docutils literal notranslate"><span class="pre">License-File</span></code> field</a></li>
<li><a class="reference internal" href="#deprecate-license-field">Deprecate <code class="docutils literal notranslate"><span class="pre">License</span></code> field</a></li>
<li><a class="reference internal" href="#deprecate-license-classifiers">Deprecate license classifiers</a></li>
</ul>
</li>
<li><a class="reference internal" href="#project-source-metadata">Project source metadata</a><ul>
<li><a class="reference internal" href="#add-string-value-to-license-key">Add string value to <code class="docutils literal notranslate"><span class="pre">license</span></code> key</a></li>
<li><a class="reference internal" href="#add-license-files-key">Add <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key</a></li>
<li><a class="reference internal" href="#deprecate-license-key-table-subkeys">Deprecate <code class="docutils literal notranslate"><span class="pre">license</span></code> key table subkeys</a></li>
</ul>
</li>
<li><a class="reference internal" href="#license-files-in-project-formats">License files in project formats</a></li>
<li><a class="reference internal" href="#converting-legacy-metadata">Converting legacy metadata</a></li>
</ul>
</li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
<li><a class="reference internal" href="#security-implications">Security Implications</a></li>
<li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a></li>
<li><a class="reference internal" href="#appendices">Appendices</a></li>
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0639.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>