CINXE.COM
PEP 639 – Improving License Clarity with Better Package Metadata | peps.python.org
<!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> » </li> <li><a href="../pep-0000/">PEP Index</a> » </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 <pombredanne at nexb.com>, C.A.M. Gerlach <CAM.Gerlach at Gerlach.CAM>, Karolina Surma <karolina.surma at gazeta.pl></dd> <dt class="field-even">PEP-Delegate<span class="colon">:</span></dt> <dd class="field-even">Brett Cannon <brett at python.org></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="Accepted and implementation complete, or no longer active">Final</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="#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> <div class="pep-banner canonical-pypa-spec sticky-banner admonition important"> <p class="admonition-title">Important</p> <p>This PEP is a historical document. The up-to-date, canonical spec, <a class="reference external" href="https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata" title="(in Python Packaging User Guide)"><span>Core metadata specifications</span></a>, is maintained on the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/">PyPA specs page</a>.</p> <p class="close-button">×</p> <p>See the <a class="reference external" href="https://www.pypa.io/en/latest/specifications/#handling-fixes-and-other-minor-updates">PyPA specification update process</a> for how to propose changes.</p> </div> <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 PEP’s 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 doesn’t 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 don’t 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 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.</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 file’s 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 distribution’s 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 project’s 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">"MIT"</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">"MIT AND (Apache-2.0 OR BSD-2-clause)"</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">"MIT OR GPL-2.0-or-later OR (FSFUL AND BSD-2-Clause)"</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">"LicenseRef-Proprietary"</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">"LICEN[CS]E*"</span><span class="p">,</span><span class="w"> </span><span class="s2">"AUTHORS*"</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">"licenses/LICENSE.MIT"</span><span class="p">,</span><span class="w"> </span><span class="s2">"licenses/LICENSE.CC0"</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">"LICENSE.txt"</span><span class="p">,</span><span class="w"> </span><span class="s2">"licenses/*"</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">"..</span><span class="se">\L</span><span class="s2">ICENSE.MIT"</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">"LICEN{CSE*"</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. It’s 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">2025-01-24 23:56:07 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <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>