peps/pep-0639/index.html

2508 lines
239 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!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: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="Python Enhancement Proposals (PEPs)">
<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;</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/12622">Discourse thread</a></dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Proposal under active discussion and revision">Draft</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></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></li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<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><ul>
<li><a class="reference internal" href="#mapping-license-classifiers-to-spdx-identifiers">Mapping license classifiers to SPDX identifiers</a></li>
</ul>
</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><ul>
<li><a class="reference internal" href="#core-metadata-fields">Core metadata fields</a><ul>
<li><a class="reference internal" href="#re-use-the-license-field">Re-use the <code class="docutils literal notranslate"><span class="pre">License</span></code> field</a></li>
<li><a class="reference internal" href="#re-use-the-license-field-with-a-value-prefix">Re-Use the <code class="docutils literal notranslate"><span class="pre">License</span></code> field with a value prefix</a></li>
<li><a class="reference internal" href="#don-t-make-license-expression-mutually-exclusive">Dont make <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> mutually exclusive</a></li>
<li><a class="reference internal" href="#don-t-deprecate-existing-license-field-and-classifiers">Dont deprecate existing <code class="docutils literal notranslate"><span class="pre">License</span></code> field and classifiers</a></li>
<li><a class="reference internal" href="#don-t-mandate-validating-new-fields-on-pypi">Dont mandate validating new fields on PyPI</a></li>
</ul>
</li>
<li><a class="reference internal" href="#source-metadata-license-key">Source metadata <code class="docutils literal notranslate"><span class="pre">license</span></code> key</a><ul>
<li><a class="reference internal" href="#add-expression-and-files-subkeys-to-table">Add <code class="docutils literal notranslate"><span class="pre">expression</span></code> and <code class="docutils literal notranslate"><span class="pre">files</span></code> subkeys to table</a></li>
<li><a class="reference internal" href="#add-an-expression-subkey-instead-of-a-string-value">Add an <code class="docutils literal notranslate"><span class="pre">expression</span></code> subkey instead of a string value</a></li>
<li><a class="reference internal" href="#define-a-new-top-level-license-expression-key">Define a new top-level <code class="docutils literal notranslate"><span class="pre">license-expression</span></code> key</a></li>
<li><a class="reference internal" href="#add-a-type-key-to-treat-text-as-expression">Add a <code class="docutils literal notranslate"><span class="pre">type</span></code> key to treat <code class="docutils literal notranslate"><span class="pre">text</span></code> as expression</a></li>
<li><a class="reference internal" href="#must-be-marked-dynamic-to-back-fill">Must be marked dynamic to back-fill</a></li>
</ul>
</li>
<li><a class="reference internal" href="#source-metadata-license-files-key">Source metadata <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key</a><ul>
<li><a class="reference internal" href="#add-a-type-subkey-to-license-files">Add a <code class="docutils literal notranslate"><span class="pre">type</span></code> subkey to <code class="docutils literal notranslate"><span class="pre">license-files</span></code></a></li>
<li><a class="reference internal" href="#only-accept-verbatim-paths">Only accept verbatim paths</a></li>
<li><a class="reference internal" href="#only-accept-glob-patterns">Only accept glob patterns</a></li>
<li><a class="reference internal" href="#infer-whether-paths-or-globs">Infer whether paths or globs</a></li>
<li><a class="reference internal" href="#also-allow-a-flat-array-value">Also allow a flat array value</a></li>
<li><a class="reference internal" href="#allow-both-paths-and-globs-subkeys">Allow both <code class="docutils literal notranslate"><span class="pre">paths</span></code> and <code class="docutils literal notranslate"><span class="pre">globs</span></code> subkeys</a></li>
<li><a class="reference internal" href="#rename-paths-subkey-to-files">Rename <code class="docutils literal notranslate"><span class="pre">paths</span></code> subkey to <code class="docutils literal notranslate"><span class="pre">files</span></code></a></li>
<li><a class="reference internal" href="#must-be-marked-dynamic-to-use-defaults">Must be marked dynamic to use defaults</a></li>
</ul>
</li>
<li><a class="reference internal" href="#license-file-paths">License file paths</a><ul>
<li><a class="reference internal" href="#flatten-license-files-in-subdirectories">Flatten license files in subdirectories</a></li>
<li><a class="reference internal" href="#resolve-name-conflicts-differently">Resolve name conflicts differently</a></li>
<li><a class="reference internal" href="#dump-directly-in-dist-info">Dump directly in <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code></a></li>
<li><a class="reference internal" href="#add-new-licenses-category-to-wheel">Add new <code class="docutils literal notranslate"><span class="pre">licenses</span></code> category to wheel</a></li>
<li><a class="reference internal" href="#name-the-subdirectory-license-files">Name the subdirectory <code class="docutils literal notranslate"><span class="pre">license_files</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#other-ideas">Other ideas</a><ul>
<li><a class="reference internal" href="#map-identifiers-to-license-files">Map identifiers to license files</a></li>
<li><a class="reference internal" href="#map-identifiers-to-source-files">Map identifiers to source files</a></li>
<li><a class="reference internal" href="#don-t-freeze-compatibility-with-a-specific-spdx-version">Dont freeze compatibility with a specific SPDX version</a></li>
<li><a class="reference internal" href="#different-licenses-for-source-and-binary-distributions">Different licenses for source and binary distributions</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#open-issues">Open Issues</a><ul>
<li><a class="reference internal" href="#should-the-license-field-be-back-filled-or-mutually-exclusive">Should the <code class="docutils literal notranslate"><span class="pre">License</span></code> field be back-filled, or mutually exclusive?</a></li>
<li><a class="reference internal" href="#should-custom-license-identifiers-be-allowed">Should custom license identifiers be allowed?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#appendix-examples">Appendix: Examples</a><ul>
<li><a class="reference internal" href="#basic-example">Basic example</a></li>
<li><a class="reference internal" href="#advanced-example">Advanced example</a></li>
<li><a class="reference internal" href="#expression-examples">Expression examples</a></li>
</ul>
</li>
<li><a class="reference internal" href="#appendix-user-scenarios">Appendix: User Scenarios</a><ul>
<li><a class="reference internal" href="#i-have-a-private-package-that-won-t-be-distributed">I have a private package that wont be distributed</a></li>
<li><a class="reference internal" href="#i-just-want-to-share-my-own-work-without-legal-restrictions">I just want to share my own work without legal restrictions</a></li>
<li><a class="reference internal" href="#i-want-to-distribute-my-project-under-a-specific-license">I want to distribute my project under a specific license</a></li>
<li><a class="reference internal" href="#i-maintain-an-existing-package-that-s-already-licensed">I maintain an existing package thats already licensed</a></li>
<li><a class="reference internal" href="#my-package-includes-other-code-under-different-licenses">My package includes other code under different licenses</a></li>
</ul>
</li>
<li><a class="reference internal" href="#appendix-license-documentation-in-python">Appendix: License Documentation in Python</a><ul>
<li><a class="reference internal" href="#license-doc-core-metadata">Core metadata</a></li>
<li><a class="reference internal" href="#setuptools-and-wheel">Setuptools and Wheel</a></li>
<li><a class="reference internal" href="#pypa-packaging-guide-and-sample-project">PyPA Packaging Guide and Sample Project</a></li>
<li><a class="reference internal" href="#python-source-code-files">Python source code files</a></li>
<li><a class="reference internal" href="#other-python-packaging-tools">Other Python packaging tools</a></li>
</ul>
</li>
<li><a class="reference internal" href="#appendix-license-documentation-in-other-projects">Appendix: License Documentation in Other Projects</a><ul>
<li><a class="reference internal" href="#linux-distribution-packages">Linux distribution packages</a></li>
<li><a class="reference internal" href="#language-and-application-packages">Language and application packages</a></li>
<li><a class="reference internal" href="#other-ecosystems">Other ecosystems</a></li>
</ul>
</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="abstract">
<span id="id1"></span><h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP defines a specification for how licenses are documented in the
<a class="reference external" href="https://packaging.python.org/specifications/core-metadata">core metadata</a>, with
<a class="reference internal" href="#spec-field-license-expression"><span class="std std-ref">license expression strings</span></a> using
<a class="reference external" href="https://spdx.dev/ids/">SPDX identifiers</a> in a new <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field.
This will make license declarations simpler and less ambiguous for
package authors to create, end users to read and understand, and
tools to programmatically process.</p>
<p>The PEP also:</p>
<ul class="simple">
<li><a class="reference internal" href="#spec-field-license-file"><span class="std std-ref">Formally specifies</span></a>
a new <code class="docutils literal notranslate"><span class="pre">License-File</span></code> field, and defines how license files should be
<a class="reference internal" href="#spec-project-formats"><span class="std std-ref">included in distributions</span></a>,
as already used by the Wheel and Setuptools projects.</li>
<li>Deprecates the legacy <code class="docutils literal notranslate"><span class="pre">License</span></code> <a class="reference internal" href="#spec-field-license"><span class="std std-ref">field</span></a>
and <code class="docutils literal notranslate"><span class="pre">license</span> <span class="pre">::</span></code> <a class="reference internal" href="#spec-field-classifier"><span class="std std-ref">classifiers</span></a>.</li>
<li><a class="reference internal" href="#spec-source-metadata"><span class="std std-ref">Adds and deprecates</span></a> the corresponding keys
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.</li>
<li><a class="reference internal" href="#spec-converting-metadata"><span class="std std-ref">Provides clear guidance</span></a> for authors and
tools converting legacy license metadata, adding license files and
validating license expressions.</li>
<li>Describes a <a class="reference internal" href="#reference-implementation"><span class="std std-ref">reference implementation</span></a>,
analyzes numerous <a class="reference internal" href="#rejected-ideas"><span class="std std-ref">potential alternatives</span></a>,
includes <a class="reference internal" href="#examples"><span class="std std-ref">detailed examples</span></a>,
explains <a class="reference internal" href="#user-scenarios"><span class="std std-ref">user scenarios</span></a> and
surveys license documentation
<a class="reference internal" href="#license-doc-python"><span class="std std-ref">in Python packaging</span></a> and
<a class="reference internal" href="#license-doc-other-projects"><span class="std std-ref">other ecosystems</span></a>.</li>
</ul>
<p>The changes in this PEP will update the
<a class="reference external" href="https://packaging.python.org/specifications/core-metadata">core metadata</a> to version 2.4, modify the
<a class="reference external" href="https://packaging.python.org/specifications/declaring-project-metadata/">project (source) metadata specification</a>,
and make minor additions 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.</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 distribution package, specifically defining:</p>
<ul class="simple">
<li>A means of specifying a SPDX license expression.</li>
<li>A method of including license texts in distributions and installed projects.</li>
</ul>
<p>The changes to the core metadata specification that this PEP requires have been
designed to minimize impact and maximize backward compatibility.
This specification builds off of existing ways to document licenses that are
already in use in popular tools (e.g. adding support to core metadata for the
<code class="docutils literal notranslate"><span class="pre">License-File</span></code> field <a class="reference internal" href="#license-doc-setuptools-wheel"><span class="std std-ref">already used</span></a>
in the Wheel and Setuptools projects) and by some package authors
(e.g. storing an SPDX license expression in the existing <code class="docutils literal notranslate"><span class="pre">License</span></code> field).</p>
<p>In addition to these proposed changes, this PEP contains guidance for tools
handling and converting these metadata, a tutorial for package authors
covering various common use cases, detailed examples of them in use,
and a comprehensive survey of license documentation in Python and other
languages.</p>
<p>It is the intent of the PEP authors to work closely with tool maintainers to
implement the recommendations for validation and warnings specified here.</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 is neutral regarding the choice of license by any particular
package author. This PEP makes no recommendation for specific licenses,
and does not require the use of a particular license documentation convention.</p>
<p>Rather, the SPDX license expression syntax proposed in this PEP provides a
simpler and more expressive mechanism to accurately document any kind of
license that applies to a Python package, whether it is open source,
free/libre, proprietary, or a combination of such.</p>
<p>This PEP also does not impose any additional restrictions when uploading to
PyPI, unless projects choose to make use of the new fields.</p>
<p>Instead, it is intended to document best practices already in use, extend them
to use a new formally-specified and supported mechanism, and provide guidance
for packaging tools on how to hand the transition and inform users accordingly.</p>
<p>This PEP also is not about license documentation in files inside projects,
though this is a <a class="reference internal" href="#license-doc-source-files"><span class="std std-ref">surveyed topic</span></a>
in an appendix, and nor does it intend to cover cases where the source and
binary distribution packages dont have <a class="reference internal" href="#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, so providing accurate license information
to Python package users is an important matter.
Today, there are multiple fields where
licenses are documented in core metadata, and there are limitations to what
can be expressed in each of them. This often leads to confusion and a lack of
clarity, both for package authors and end users.</p>
<p>Many package authors have expressed difficulty and frustrations due to the
limited capabilities to express licensing in project metadata, and this
creates further trouble for Linux and BSD distribution re-packagers.
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 clear, precise and standardized license metadata</a>.</p>
<p>The current license classifiers address some common cases, and could
be extended to include the full range of current SPDX identifiers
while deprecating the many ambiguous classifiers
(including some popular and problematic ones,
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>).
However, this requires a substantial amount of effort
to duplicate the SPDX license list and keep it in sync.
Furthermore, it is effectively a hard break in backward compatibility,
forcing a huge proportion of package authors to immediately update to new
classifiers (in most cases, with many possible choices that require closely
examining the projects license) immediately when PyPI deprecates the old ones.</p>
<p>Furthermore, this only covers simple packages entirely under a single license;
it doesnt address the substantial fraction of common projects that vendor
dependencies (e.g. Setuptools), offer a choice of licenses (e.g. Packaging)
or were relicensed, adapt code from other projects or contain fonts, images,
examples, binaries or other assets under other licenses. It also requires
both authors and tools understand and implement the PyPI-specific bespoke
classifier system, rather than using short, easy to add and standardized
SPDX identifiers in a simple text field, as increasingly widely adopted by
most other packaging systems to reduce the overall burden on the ecosystem.
Finally, this does not provide as clear an indicator that a package
has adopted the new system, and should be treated accordingly.</p>
<p>On average, Python packages tend to have more ambiguous and missing license
information than other common ecosystems (such as npm, Maven or
Gem). 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> incubated effort to help
improve licensing clarity of other FOSS projects, covering all packages
from PyPI, Maven, npm and Rubygems.</p>
</section>
<section id="rationale">
<span id="id5"></span><h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>A survey of existing license metadata definitions in use in the Python
ecosystem today is provided in
<a class="reference internal" href="#license-doc-python"><span class="std std-ref">an appendix</span></a> of this PEP,
and license documentation in a variety of other packaging systems,
Linux distros, languages ecosystems and applications is surveyed in
<a class="reference internal" href="#license-doc-other-projects"><span class="std std-ref">another appendix</span></a>.</p>
<p>There are a few takeaways from the survey, which have guided the design
and recommendations of this PEP:</p>
<ul class="simple">
<li>Most package formats use a single <code class="docutils literal notranslate"><span class="pre">License</span></code> field.</li>
<li>Many modern package systems use some form of license expression syntax to
optionally combine more than one license identifier together.
SPDX and SPDX-like syntaxes are the most popular in use.</li>
<li>SPDX license identifiers are becoming the de facto way to reference common
licenses everywhere, whether or not a full license expression syntax is used.</li>
<li>Several package formats support documenting both a license expression and the
paths of the corresponding files that contain the license text. Most Free and
Open Source Software licenses require package authors to include their full
text in a distribution.</li>
</ul>
<p>The use of a new <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field will provide an intuitive,
structured and unambiguous way to express the license of a
package using a well-defined syntax and well-known license identifiers.
Similarly, a formally-specified <code class="docutils literal notranslate"><span class="pre">License-File</span></code> field offers a standardized
way to ensure that the full text of the license(s) are included with the
package when distributed, as legally required, and allows other tools consuming
the core metadata to unambiguously locate a distributions license files.</p>
<p>While dramatically simplifying and improving the present Python license
metadata story, this specification standardizes and 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.
Furthermore, 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">already successfully implemented</a> in the popular
PyPA <a class="reference external" href="https://hatch.pypa.io/latest/">Hatch</a> packaging tool, and an earlier draft of the
license files portion is <a class="reference external" href="https://github.com/pypa/setuptools/pull/2645">implemented in Setuptools</a>.</p>
<p>Over time, encouraging the use of these fields and deprecating the ambiguous,
duplicative and confusing legacy alternatives will help Python software
publishers improve the clarity, accuracy and portability of their licensing
practices, to the benefit of package authors, consumers and redistributors
alike.</p>
</section>
<section id="terminology">
<span id="id6"></span><h2><a class="toc-backref" href="#terminology" role="doc-backlink">Terminology</a></h2>
<p>This PEP seeks to clearly define the terms it uses, given that some have
multiple established meanings (e.g. import vs. distribution package,
wheel <em>format</em> vs. Wheel <em>project</em>); are related and often used
interchangeably, but have critical distinctions in meaning
(e.g. <code class="docutils literal notranslate"><span class="pre">[project]</span></code> <em>key</em> vs. core metadata <em>field</em>); are existing concepts
that dont have formal terms/definitions (e.g. project/source metadata vs.
distribution/built metadata, build vs. publishing tools), or are new concepts
introduced here (e.g. license expression/identifier).</p>
<p>This PEP also uses terms defined in the
<a class="reference external" href="https://packaging.python.org/glossary/">PyPA PyPUG Glossary</a>
(specifically <em>built/binary distribution</em>, <em>distribution package</em>,
<em>project</em> and <em>source distribution</em>), and by the <a class="reference external" href="https://spdx.dev/">SPDX Project</a>
(<em>license identifier</em>, <em>license expression</em>).</p>
<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>
<p>Terms are listed here in their full versions;
related words (<code class="docutils literal notranslate"><span class="pre">Rel:</span></code>) are in parenthesis,
including short forms (<code class="docutils literal notranslate"><span class="pre">Short:</span></code>), sub-terms (<code class="docutils literal notranslate"><span class="pre">Sub:</span></code>) and common synonyms
for the purposes of this PEP (<code class="docutils literal notranslate"><span class="pre">Syn:</span></code>).</p>
<dl>
<dt><strong>Core Metadata</strong> <em>(Syn: Package Metadata, Sub: Distribution Metadata)</em></dt><dd>The <a class="reference external" href="https://packaging.python.org/specifications/core-metadata">PyPA specification</a> and the set of metadata fields
it defines that describe key static attributes of distribution packages
and installed projects.<p>The <strong>distribution metadata</strong> refers to, more specifically, the concrete form
core metadata takes when included inside a distribution archive
(<code class="docutils literal notranslate"><span class="pre">PKG-INFO</span></code> in a sdist and <code class="docutils literal notranslate"><span class="pre">METADATA</span></code> in a wheel) or installed project
(<code class="docutils literal notranslate"><span class="pre">METADATA</span></code>).</p>
</dd>
<dt><strong>Core Metadata Field</strong> <em>(Short: Metadata Field/Field)</em></dt><dd>A single key-value pair, or sequence of such with the same key, as defined
by the <a class="reference external" href="https://packaging.python.org/specifications/core-metadata">core metadata specification</a>.
Notably, distinct from a <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table <em>key</em>.</dd>
<dt><strong>Distribution Package</strong> <em>(Sub: Package, Distribution Archive)</em></dt><dd>(<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Distribution-Package">See PyPUG</a>)
In this PEP, <strong>package</strong> is used to refer to the abstract concept of a
distributable form of a Python project, while <strong>distribution</strong> more
specifically references the physical <strong>distribution archive</strong>.</dd>
<dt><strong>License Classifier</strong></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/#classifier-multiple-use">described in the core metadata specification</a>)
which begins with <code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span></code>, currently used to indicate
a projects license status by including it as a <code class="docutils literal notranslate"><span class="pre">Classifier</span></code>
in the core metadata.</dd>
<dt><strong>License Expression</strong> <em>(Syn: SPDX Expression)</em></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 any SPDX license identifiers as defined here, which describes
a projects license(s) and how they relate to one another. 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><strong>License Identifier</strong> <em>(Syn: License ID/SPDX Identifier)</em></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; briefly,
this includes all valid SPDX identifiers and the <code class="docutils literal notranslate"><span class="pre">LicenseRef-Public-Domain</span></code>
and <code class="docutils literal notranslate"><span class="pre">LicenseRef-Proprietary</span></code> strings. 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></dd>
<dt><strong>Project</strong> <em>(Sub: Project Source Tree, Installed Project)</em></dt><dd>(<a class="reference external" href="https://packaging.python.org/en/latest/glossary/#term-Project">See PyPUG</a>)
Here, a <strong>project source tree</strong> refers to the on-disk format of
a project used for development, while an <strong>installed project</strong> is the form a
project takes once installed from a distribution, as
<a class="reference external" href="https://packaging.python.org/specifications/recording-installed-packages/">specified by PyPA</a>.</dd>
<dt><strong>Project Source Metadata</strong> <em>(Sub: Project Table Metadata, Key, Subkey)</em></dt><dd>Core metadata defined by the package author in the project source tree,
as top-level keys in the <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table of a <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> file,
in the <code class="docutils literal notranslate"><span class="pre">[metadata]</span></code> table of <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code>, or the equivalent for other
build tools.<p>The <strong>Project Table Metadata</strong>, or <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> <code class="docutils literal notranslate"><span class="pre">[project]</span></code> metadata,
refers specifically to the former, as defined by the
<a class="reference external" href="https://packaging.python.org/specifications/declaring-project-metadata/">PyPA Declaring Project Metadata specification</a>
and originally specified in <a class="pep reference internal" href="../pep-0621/" title="PEP 621 Storing project metadata in pyproject.toml">PEP 621</a>.
A <strong>Project Table Key</strong>, or an unqualified <em>key</em> refers specifically to
a top-level <code class="docutils literal notranslate"><span class="pre">[project]</span></code> key
(notably, distinct from a core metadata <em>field</em>),
while a <strong>subkey</strong> refers to a second-level key in a table-valued
<code class="docutils literal notranslate"><span class="pre">[project]</span></code> key.</p>
</dd>
<dt><strong>Root License Directory</strong> <em>(Short: License Directory)</em></dt><dd>The directory under which license files are stored in a project/distribution
and the root directory that their paths, as recorded under the
<code class="docutils literal notranslate"><span class="pre">License-File</span></code> core metadata fields, are relative to.
Defined here to be the project root directory for source trees and source
distributions, and a subdirectory named <code class="docutils literal notranslate"><span class="pre">licenses</span></code> of the directory
containing the core metadata (i.e., the <code class="docutils literal notranslate"><span class="pre">.dist-info/licenses</span></code>
directory) for built distributions and installed projects.</dd>
<dt><strong>Tool</strong> <em>(Sub: Packaging Tool, Build Tool, Install Tool, Publishing Tool)</em></dt><dd>A program, script or service executed by the user or automatically that
seeks to conform to the specification defined in this PEP.<p>A <strong>packaging tool</strong> refers to a tool used to build, publish,
install, or otherwise directly interact with Python packages.</p>
<p>A <strong>build tool</strong> is a packaging tool used to generate a source or built
distribution from a project source tree or sdist, when directly invoked
as such (as opposed to by end-user-facing install tools).
Examples: Wheel project, <a class="pep reference internal" href="../pep-0517/" title="PEP 517 A build-system independent format for source trees">PEP 517</a> backends via <code class="docutils literal notranslate"><span class="pre">build</span></code> or other
package-developer-facing frontends, calling <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> directly.</p>
<p>An <strong>install tool</strong> is a packaging tool used to install a source or built
distribution in a target environment. Examples include the PyPA pip and
<code class="docutils literal notranslate"><span class="pre">installer</span></code> projects.</p>
<p>A <strong>publishing tool</strong> is a packaging tool used to upload distribution
archives to a package index, such as Twine for PyPI.</p>
</dd>
<dt><strong>Wheel</strong> <em>(Short: wheel, Rel: wheel format, Wheel project)</em></dt><dd>Here, <strong>wheel</strong>, the standard built distribution format introduced in
<a class="pep reference internal" href="../pep-0427/" title="PEP 427 The Wheel Binary Package Format 1.0">PEP 427</a> and <a class="reference external" href="https://packaging.python.org/specifications/binary-distribution-format/">specified by the PyPA</a>, will be referred to in
lowercase, while the <a class="reference external" href="https://wheel.readthedocs.io/en/stable/">Wheel project</a>, its reference
implementation, will be referred to as such with <strong>Wheel</strong> in Title Case.</dd>
</dl>
</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 the improved license handling outlined in
this PEP include those in both
<a class="reference internal" href="#spec-core-metadata"><span class="std std-ref">distribution package metadata</span></a>,
as defined in the <a class="reference external" href="https://packaging.python.org/specifications/core-metadata">core metadata specification</a>, and
<a class="reference internal" href="#spec-source-metadata"><span class="std std-ref">author-provided project source metadata</span></a>,
as defined in the <a class="reference external" href="_pep621spec">project source metadata specification</a>
(and originally introduced in <a class="pep reference internal" href="../pep-0621/" title="PEP 621 Storing project metadata in pyproject.toml">PEP 621</a>).</p>
<p>Further, <a class="reference internal" href="#spec-project-formats"><span class="std std-ref">minor additions</span></a> to the
source distribution (sdist), built distribution (wheel) and installed project
specifications will help document and clarify the already allowed,
now formally standardized behavior in these respects.
Finally, <a class="reference internal" href="#spec-converting-metadata"><span class="std std-ref">guidance is established</span></a>
for tools handling and converting legacy license metadata to license
expressions, to ensure the results are consistent, correct and unambiguous.</p>
<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="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 <a class="reference external" href="https://packaging.python.org/specifications/core-metadata">PyPA Core Metadata specification</a> defines the names
and semantics of each of the supported fields in the distribution metadata of
Python distribution packages and installed projects.</p>
<p>This PEP <a class="reference internal" href="#spec-field-license-expression"><span class="std std-ref">adds</span></a> the
<code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field,
<a class="reference internal" href="#spec-field-license-file"><span class="std std-ref">adds</span></a> the <code class="docutils literal notranslate"><span class="pre">License-File</span></code> field,
<a class="reference internal" href="#spec-field-license"><span class="std std-ref">deprecates</span></a> the <code class="docutils literal notranslate"><span class="pre">License</span></code> field,
and <a class="reference internal" href="#spec-field-classifier"><span class="std std-ref">deprecates</span></a> the license classifiers
in the <code class="docutils literal notranslate"><span class="pre">Classifier</span></code> field.</p>
<p>The error and warning guidance in this section applies to build and
publishing tools; end-user-facing install tools MAY be more lenient 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 to version 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 field is specified to contain a text string
that is a valid SPDX license expression, as defined herein.</p>
<p>Publishing tools SHOULD issue an informational warning if this field is
missing, and MAY raise an error. Build tools MAY issue a similar warning,
but MUST NOT raise an error.</p>
<p id="license-expression-definition">A license expression is a string using 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>When used in the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field and as a specialization of
the SPDX license expression definition, a license expression can use the
following license identifiers:</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 <code class="docutils literal notranslate"><span class="pre">LicenseRef-Public-Domain</span></code> and <code class="docutils literal notranslate"><span class="pre">LicenseRef-Proprietary</span></code> strings, to
identify licenses that are not included in the SPDX license list.</li>
</ul>
<p>When processing the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field to determine if it contains
a valid license expression, build and publishing tools:</p>
<ul class="simple">
<li>SHOULD halt execution and raise an error if:<ul>
<li>The field does not contain a valid license expression</li>
<li>One or more license identifiers are not valid
(as <a class="reference internal" href="#license-expression-definition"><span class="std std-ref">defined above</span></a>)</li>
</ul>
</li>
<li>SHOULD report an informational 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>.</li>
<li>MUST 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.</li>
<li>SHOULD report an informational warning, and MAY raise an error if
the normalization process results in changes to the
<code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field contents.</li>
</ul>
<p>For all newly-upload distributions 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 it contains a valid, case-normalized license expression with
valid identifiers (as defined here) and MUST reject uploads that do not.
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>Each instance of the <code class="docutils literal notranslate"><span class="pre">License-File</span></code> optional field is specified to contain
the string representation of the path in the project source tree, relative to
the project root directory, of a license-related file.
It is a multi-use field that may appear zero or
more times, each instance listing 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 root license directory in both
installed projects and the standardized distribution package types.
In other legacy, non-standard or new distribution package formats and
mechanisms of accessing and storing core metadata, the value MAY correspond
to the license file path relative to a format-defined root license directory.
Alternatively, it MAY be treated as a unique abstract key to access the
license file contents by another means, as specified by the format.</p>
<p>If a <code class="docutils literal notranslate"><span class="pre">License-File</span></code> is listed in a source or built distributions core
metadata, that file MUST be included in the distribution at the specified path
relative to the root license directory, and MUST be installed with the
distribution at that same relative path.</p>
<p>The specified relative path MUST be consistent between project source trees,
source distributions (sdists), built distributions (wheels) and installed
projects. Therefore, 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.</p>
<p>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.
License file content MUST be UTF-8 encoded text.</p>
<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 distribution packages that include one or more
<code class="docutils literal notranslate"><span class="pre">License-File</span></code> fields 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 the specified files are present in all
uploaded distributions, 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> field is deprecated and replaced by
the new <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field. Build and publishing tools MUST raise
an error if both these fields are present and their values are not identical,
including capitalization and excluding leading and trailing whitespace.</p>
<p>If only the <code class="docutils literal notranslate"><span class="pre">License</span></code> field is present, such tools SHOULD 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 distributions 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 a <code class="docutils literal notranslate"><span class="pre">License</span></code> field and the text of which is not
identical to that of <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code>, as defined in this section.</p>
<p>Along with license classifiers, 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 license <a class="reference external" href="https://pypi.org/classifiers">classifiers</a> in the <code class="docutils literal notranslate"><span class="pre">Classifier</span></code> field
(<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 SHOULD and
publishing tools MUST 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, build tools MAY
and publishing tools SHOULD 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>For all newly-uploaded distributions 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 also specify any license classifiers.</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.
Along with the <code class="docutils literal notranslate"><span class="pre">License</span></code> field, 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>As originally introduced in <a class="pep reference internal" href="../pep-0621/" title="PEP 621 Storing project metadata in pyproject.toml">PEP 621</a>, the
<a class="reference external" href="https://packaging.python.org/specifications/declaring-project-metadata/">PyPA Declaring Project Metadata specification</a>
defines how to declare a 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 for
build tools to consume and output distribution core metadata.</p>
<p>This PEP <a class="reference internal" href="#spec-key-license-expression"><span class="std std-ref">adds</span></a>
a top-level string value for the <code class="docutils literal notranslate"><span class="pre">license</span></code> key,
<a class="reference internal" href="#spec-key-license-files"><span class="std std-ref">adds</span></a> the new <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key
and <a class="reference internal" href="#spec-key-license"><span class="std std-ref">deprecates</span></a>
the table value for the <code class="docutils literal notranslate"><span class="pre">license</span></code> key
along with its corresponding 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>.</p>
<section id="add-string-value-to-license-key">
<span id="spec-key-license-expression"></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>A top-level string value is defined
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,
which is specified to be a valid SPDX license expression,
as <a class="reference internal" href="#license-expression-definition"><span class="std std-ref">defined previously</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 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.
When generating the core metadata, tools MUST perform case normalization.</p>
<p>If a top-level string value for the <code class="docutils literal notranslate"><span class="pre">license</span></code> key is present and valid,
for purposes of backward compatibility
tools MAY back-fill the <code class="docutils literal notranslate"><span class="pre">License</span></code> core metadata field
with the normalized value of the <code class="docutils literal notranslate"><span class="pre">license</span></code> key.</p>
</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 a table, which if present MUST contain one of two optional,
mutually exclusive subkeys, <code class="docutils literal notranslate"><span class="pre">paths</span></code> and <code class="docutils literal notranslate"><span class="pre">globs</span></code>; if both are specified,
tools MUST raise an error. Both are arrays of strings; the <code class="docutils literal notranslate"><span class="pre">paths</span></code> subkey
contains verbatim file paths, and the <code class="docutils literal notranslate"><span class="pre">globs</span></code> subkey valid glob patterns,
which MUST be parsable by the <code class="docutils literal notranslate"><span class="pre">glob</span></code> <a class="reference external" href="https://docs.python.org/3/library/glob.html">module</a> in the
Python standard library.</p>
<p><strong>Note</strong>: To avoid ambiguity, confusion and (per <a class="pep reference internal" href="../pep-0020/" title="PEP 20 The Zen of Python">PEP 20</a>, the Zen of Python)
“more than one (obvious) way to do it”, allowing a flat array of strings
as the value for the <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key has been
<a class="reference internal" href="#license-files-allow-flat-array"><span class="std std-ref">left out for now</span></a>.</p>
<p>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.
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>If the <code class="docutils literal notranslate"><span class="pre">paths</span></code> subkey is a non-empty array, build tools:</p>
<ul class="simple">
<li>MUST treat each value as a verbatim, literal file path, and
MUST NOT treat them as glob patterns.</li>
<li>MUST include each listed file in all distribution archives.</li>
<li>MUST NOT match any additional license files beyond those explicitly
statically specified by the user under the <code class="docutils literal notranslate"><span class="pre">paths</span></code> subkey.</li>
<li>MUST list each 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 one or more paths do not correspond to a valid file
in the project source that can be copied into the distribution archive.</li>
</ul>
<p>If the <code class="docutils literal notranslate"><span class="pre">globs</span></code> subkey is a non-empty array, 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 at least one listed pattern in all
distribution archives.</li>
<li>MAY exclude files matched by glob patterns that can be unambiguously
determined to be backup, temporary, hidden, OS-generated or VCS-ignored.</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>SHOULD issue a warning and MAY raise an error if no files are matched.</li>
<li>MAY issue a warning 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 the <code class="docutils literal notranslate"><span class="pre">paths</span></code> or <code class="docutils literal notranslate"><span class="pre">globs</span></code> subkey
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 id="default-patterns">If the <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key is not present and not explicitly marked as
<code class="docutils literal notranslate"><span class="pre">dynamic</span></code>, tools MUST assume a default value of the following:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="n">license-files</span><span class="p">.</span><span class="n">globs</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;COPYING*&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;NOTICE*&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;AUTHORS*&quot;</span><span class="p">]</span>
</pre></div>
</div>
<p>In this case, tools MAY issue a warning if no license files are matched,
but MUST NOT raise an error.</p>
<p>If the <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key is marked as <code class="docutils literal notranslate"><span class="pre">dynamic</span></code> (and not present),
to preserve consistent behavior with current tools and help ensure the packages
they create are legally distributable, build tools SHOULD default to
including at least the license files matching the above patterns, unless the
user has explicitly specified their own.</p>
</section>
<section id="deprecate-license-key-table-subkeys">
<span id="spec-key-license"></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.paths</span></code> field.
If the file does not exist at the specified path,
tools MUST raise an informative error as previously specified.
However, tools MUST also still assume the
<a class="reference internal" href="#default-patterns"><span class="std std-ref">specified default value</span></a>
for the <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key and also include,
in addition to a license file specified under the <code class="docutils literal notranslate"><span class="pre">license.file</span></code> subkey,
any license files that match the specified list of patterns.</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 minor additions will be made to the relevant existing specifications
to document, standardize and clarify what is already currently supported,
allowed and implemented behavior, as well as explicitly mention the root
license directory the license files are located in and relative to for
each format, per the <a class="reference internal" href="#spec-field-license-file"><span class="std std-ref">Add License-File field</span></a> section.</p>
<dl class="simple">
<dt><strong>Project source trees</strong></dt><dd>As described in the <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/specifications/declaring-project-metadata/">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><strong>Source distributions</strong> <em>(sdists)</em></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 for
<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 <code class="docutils literal notranslate"><span class="pre">License-File</span></code> in the <code class="docutils literal notranslate"><span class="pre">PKG-INFO</span></code> at their
respective paths relative to the top-level directory 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><strong>Built distributions</strong> <em>(wheels)</em></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><strong>Installed projects</strong></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>
<section id="mapping-license-classifiers-to-spdx-identifiers">
<span id="spec-mapping-classifiers-identifiers"></span><h4><a class="toc-backref" href="#mapping-license-classifiers-to-spdx-identifiers" role="doc-backlink">Mapping license classifiers to SPDX identifiers</a></h4>
<p>Most single license classifiers (namely, all those not mentioned below)
map to a single valid SPDX license identifier,
allowing tools to infer the SPDX license identifier they correspond to,
both for use when analyzing and auditing packages,
and providing a semi-automated mechanism of filling the <code class="docutils literal notranslate"><span class="pre">license</span></code> key
or the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field
following the <a class="reference internal" href="#spec-converting-metadata"><span class="std std-ref">specification above</span></a>.</p>
<p>Some legacy license classifiers intend to specify a particular license,
but do not specify the particular version or variant, leading to a
<a class="reference external" href="https://github.com/pypa/trove-classifiers/issues/17">critical ambiguity</a>
as to their terms, compatibility and acceptability.
Tools MUST NOT attempt to automatically infer a <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code>
when one of these classifiers is used without affirmative user action:</p>
<ul class="simple">
<li><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">Academic</span> <span class="pre">Free</span> <span class="pre">License</span> <span class="pre">(AFL)</span></code></li>
<li><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">Apache</span> <span class="pre">Software</span> <span class="pre">License</span></code></li>
<li><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">Apple</span> <span class="pre">Public</span> <span class="pre">Source</span> <span class="pre">License</span></code></li>
<li><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">Artistic</span> <span class="pre">License</span></code></li>
<li><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></li>
<li><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">GNU</span> <span class="pre">Affero</span> <span class="pre">General</span> <span class="pre">Public</span> <span class="pre">License</span> <span class="pre">v3</span></code></li>
<li><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">GNU</span> <span class="pre">Free</span> <span class="pre">Documentation</span> <span class="pre">License</span> <span class="pre">(FDL)</span></code></li>
<li><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">GNU</span> <span class="pre">General</span> <span class="pre">Public</span> <span class="pre">License</span> <span class="pre">(GPL)</span></code></li>
<li><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">GNU</span> <span class="pre">General</span> <span class="pre">Public</span> <span class="pre">License</span> <span class="pre">v2</span> <span class="pre">(GPLv2)</span></code></li>
<li><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">GNU</span> <span class="pre">General</span> <span class="pre">Public</span> <span class="pre">License</span> <span class="pre">v3</span> <span class="pre">(GPLv3)</span></code></li>
<li><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">GNU</span> <span class="pre">Lesser</span> <span class="pre">General</span> <span class="pre">Public</span> <span class="pre">License</span> <span class="pre">v2</span> <span class="pre">(LGPLv2)</span></code></li>
<li><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">GNU</span> <span class="pre">Lesser</span> <span class="pre">General</span> <span class="pre">Public</span> <span class="pre">License</span> <span class="pre">v2</span> <span class="pre">or</span> <span class="pre">later</span> <span class="pre">(LGPLv2+)</span></code></li>
<li><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">GNU</span> <span class="pre">Lesser</span> <span class="pre">General</span> <span class="pre">Public</span> <span class="pre">License</span> <span class="pre">v3</span> <span class="pre">(LGPLv3)</span></code></li>
<li><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">GNU</span> <span class="pre">Library</span> <span class="pre">or</span> <span class="pre">Lesser</span> <span class="pre">General</span> <span class="pre">Public</span> <span class="pre">License</span> <span class="pre">(LGPL)</span></code></li>
</ul>
<p>A comprehensive mapping of these classifiers to their possible specific
identifiers was <a class="reference external" href="https://github.com/pypa/trove-classifiers/issues/17#issuecomment-385027197">assembled by Dustin Ingram</a>, which tools
MAY use as a reference for the identifier selection options to offer users
when prompting the user to explicitly select the license identifier
they intended for their project.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Several additional classifiers, namely the “or later” variants of
the AGPLv3, GPLv2, GPLv3 and LGPLv3, are also listed in the aforementioned
mapping, but unambiguously map to their respective licenses,
and so are not listed here.
However, LGPLv2 is included above, as it could ambiguously
refer to either the distinct v2.0 or v2.1 variants of that license.</p>
</div>
<p>In addition, for the various special cases, the following mappings are
considered canonical and normative for the purposes of this specification:</p>
<ul>
<li>Classifier <code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">Public</span> <span class="pre">Domain</span></code> MAY be mapped to the generic
<code class="docutils literal notranslate"><span class="pre">License-Expression:</span> <span class="pre">LicenseRef-Public-Domain</span></code>.
If tools do so, they SHOULD issue an informational warning encouraging
the use of more explicit and legally portable license identifiers,
such as those for the <a class="reference external" href="https://creativecommons.org/publicdomain/zero/1.0/">CC0 1.0 license</a> (<code class="docutils literal notranslate"><span class="pre">CC0-1.0</span></code>),
the <a class="reference external" href="https://unlicense.org/">Unlicense</a> (<code class="docutils literal notranslate"><span class="pre">Unlicense</span></code>),
or the <a class="reference external" href="https://opensource.org/licenses/MIT">MIT license</a> (<code class="docutils literal notranslate"><span class="pre">MIT</span></code>),
since the meaning associated with the term “public domain” is thoroughly
dependent on the specific legal jurisdiction involved,
some of which lack the concept entirely.
Alternatively, tools MAY choose to treat these classifiers as ambiguous.</li>
<li>The generic and sometimes ambiguous classifiers:<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">Free</span> <span class="pre">For</span> <span class="pre">Educational</span> <span class="pre">Use</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">Free</span> <span class="pre">For</span> <span class="pre">Home</span> <span class="pre">Use</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">Free</span> <span class="pre">for</span> <span class="pre">non-commercial</span> <span class="pre">use</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">Freely</span> <span class="pre">Distributable</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">Free</span> <span class="pre">To</span> <span class="pre">Use</span> <span class="pre">But</span> <span class="pre">Restricted</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">Freeware</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">Other/Proprietary</span> <span class="pre">License</span></code></li>
</ul>
<p>MAY be mapped to the generic
<code class="docutils literal notranslate"><span class="pre">License-Expression:</span> <span class="pre">LicenseRef-Proprietary</span></code>,
but tools MUST issue a prominent, informative warning if they do so.
Alternatively, tools MAY choose to treat these classifiers as ambiguous.</p>
</li>
<li>The generic and ambiguous classifiers <code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">OSI</span> <span class="pre">Approved</span></code> and
<code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">DFSG</span> <span class="pre">approved</span></code> do not map to any license expression,
and thus tools SHOULD treat them as ambiguous, or if not MUST ignore them.</li>
<li>The classifiers <code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">GUST</span> <span class="pre">Font</span> <span class="pre">License</span> <span class="pre">1.0</span></code> and
<code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span> <span class="pre">GUST</span> <span class="pre">Font</span> <span class="pre">License</span> <span class="pre">2006-09-30</span></code> have no mapping to SPDX license
identifiers, and no PyPI package uses them as of 2022-07-09.</li>
</ul>
<p>When multiple license classifiers are used, their relationship is ambiguous,
and it is typically not possible to determine if all the licenses apply or if
there is a choice that is possible among the licenses,
In this case, tools MUST NOT automatically infer a license expression,
unless one license classifier is a parent of the other,
i.e. the child contains all <code class="docutils literal notranslate"><span class="pre">::</span></code>-delineated components of the parent,
in which case tools MAY ignore the parent classifier
but SHOULD issue an informative warning when doing so.</p>
</section>
</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, dedicated <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 reserved for this purpose
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 signals 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, and raises an error if and only if the user affirmatively
upgrades to the latest metadata version and adds the new field/key.</p>
<p>The legacy <code class="docutils literal notranslate"><span class="pre">License</span></code> core metadata field
and the <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
will be deprecated along with the license classifiers,
retaining backwards compatibility while gently preparing users for their
future removal. Such a removal would follow a suitable transition period, and
be left to a future PEP and a new version of the core metadata specification.</p>
<p>Formally specifying the new <code class="docutils literal notranslate"><span class="pre">License-File</span></code> core metadata field and the
inclusion of the listed files in the distribution merely codifies and
refines the existing practices in popular packaging tools, including the Wheel
and Setuptools projects, and is designed to be largely backwards-compatible
with their existing use of that field. Likewise, 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>
standardizes statically specifying the files to include,
as well as the default behavior, and allows other tools to make use of them,
while only having an effect once users and tools expressly adopt it.</p>
<p>Due to requiring license files not be flattened into <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> and
specifying that they should be placed in a dedicated <code class="docutils literal notranslate"><span class="pre">licenses</span></code> subdir,
wheels produced following this change will have differently-located
licenses relative to those produced via the previous unspecified,
installer-specific behavior, but as until this PEP there was no way of
discovering these files or accessing them programmatically, and this will
be further discriminated by a new metadata version, there arent any foreseen
mechanism for this to pose a practical issue.</p>
<p>Furthermore, this resolves existing compatibility issues with the current
ad hoc behavior, namely license files being silently clobbered if they have
the same names as others at different paths, unknowingly rendering the wheel
undistributable, and conflicting with the names of other metadata files in
the same directory. Formally specifying otherwise would in fact block full
forward compatibility with additional standard or installer-specified files
and directories added to <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code>, as they too could conflict with
the names of existing licenses.</p>
<p>While minor additions will be made to the source distribution (sdist),
built distribution (wheel) and installed project specifications, all of these
are merely documenting, clarifying and formally specifying behaviors explicitly
allowed under their current respective specifications, and already implemented
in practice, and gating them behind the explicit presence of both the new
metadata versions and the new fields. In particular, sdists may contain
arbitrary files following the project source tree layout, and formally
mentioning that these must include the license files listed in the metadata
merely documents and codifies existing Setuptools practice. Likewise, arbitrary
installer-specific files are allowed in the <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directory of wheels
and copied to installed projects, and again this PEP just formally clarifies
and standardizes what is already being done.</p>
<p>Finally, while this PEP does propose 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, this has no effect on
existing packages, nor any effect on any new distributions uploaded unless they
explicitly choose to opt in to using these new fields while not
following the requirements in the specification. Therefore, this does not have
a backward compatibility impact, and in fact ensures forward compatibility with
any future changes by ensuring all distributions uploaded to PyPI with the new
fields are valid and 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>The simple cases are simple: a single license identifier is a valid license
expression, and a large majority of packages use a single license.</p>
<p>The plan to teach users of packaging tools how to express their packages
license with a valid license expression is to have tools issue informative
messages when they detect invalid license expressions, or when the deprecated
<code class="docutils literal notranslate"><span class="pre">License</span></code> field or license classifiers are used.</p>
<p>An immediate, descriptive error message if an invalid <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code>
is used will help users understand they need to use SPDX identifiers in
this field, and catch them if they make a mistake.
For authors still using the now-deprecated, less precise and more redundant
<code class="docutils literal notranslate"><span class="pre">License</span></code> field or license classifiers, packaging tools will warn
them and inform them of the modern replacement, <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code>.
Finally, for users who may have forgotten or not be aware they need to do so,
publishing tools will gently guide them toward including <code class="docutils literal notranslate"><span class="pre">license</span></code>
and <code class="docutils literal notranslate"><span class="pre">license-files</span></code> in their project source metadata.</p>
<p>Tools may also help with the conversion and suggest a license expression in
many, if not most common cases:</p>
<ul class="simple">
<li>The section <a class="reference internal" href="#spec-mapping-classifiers-identifiers"><span class="std std-ref">Mapping license classifiers to SPDX identifiers</span></a> provides
tool authors with guidelines on how to suggest a license expression produced
from legacy classifiers.</li>
<li>Tools may also be able to infer and 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>.
For instance, a tool may suggest converting a value of <code class="docutils literal notranslate"><span class="pre">MIT</span></code>
in the <code class="docutils literal notranslate"><span class="pre">license.text</span></code> key in <code class="docutils literal notranslate"><span class="pre">[project]</span></code>
(or the equivalent in tool-specific formats)
to a top-level string value of the <code class="docutils literal notranslate"><span class="pre">license</span></code> key (or equivalent).
Likewise, a tool could suggest converting from a <code class="docutils literal notranslate"><span class="pre">License</span></code> of <code class="docutils literal notranslate"><span class="pre">Apache2</span></code>
(which is not a valid license expression
as <a class="reference internal" href="#spec-field-license-expression"><span class="std std-ref">defined in this PEP</span></a>)
to a <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> of <code class="docutils literal notranslate"><span class="pre">Apache-2.0</span></code>
(the equivalent valid license expression using an SPDX license identifier).</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.</p>
<p>The <a class="reference external" href="https://github.com/nexB/license-expression/">license-expression library</a> is a reference Python
implementation that handles license expressions including parsing,
formatting and validation, using flexible lists of license symbols
(including SPDX license IDs and any extra identifiers included here).
It is licensed under Apache-2.0 and is already used in several projects,
including the <a class="reference external" href="https://github.com/spdx/tools-python/">SPDX Python Tools</a>,
the <a class="reference external" href="https://github.com/nexB/scancode-toolkit">ScanCode toolkit</a>
and the Free Software Foundation Europe (FSFE) <a class="reference external" href="https://reuse.software/">REUSE project</a>.</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>
<section id="core-metadata-fields">
<h3><a class="toc-backref" href="#core-metadata-fields" role="doc-backlink">Core metadata fields</a></h3>
<p>Potential alternatives to the structure, content and deprecation of the
core metadata fields specified in this PEP.</p>
<section id="re-use-the-license-field">
<h4><a class="toc-backref" href="#re-use-the-license-field" role="doc-backlink">Re-use the <code class="docutils literal notranslate"><span class="pre">License</span></code> field</a></h4>
<p>Following <a class="reference external" href="https://github.com/pombredanne/spdx-pypi-pep/issues/7">initial discussion</a>, earlier versions of this
PEP proposed re-using the existing <code class="docutils literal notranslate"><span class="pre">License</span></code> field, which tools would
attempt to parse as a SPDX license expression with a fallback to free text.
Initially, this would merely cause a warning (or even pass silently),
but would eventually be treated as an error by modern tooling.</p>
<p>This offered the potential benefit of greater backwards-compatibility,
easing the community into using SPDX license expressions while taking advantage
of packages that already have them (either intentionally or coincidentally),
and avoided adding yet another license-related field.</p>
<p>However, following substantial discussion, consensus was reached that a
dedicated <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field was the preferred overall approach.
The presence of this field is an unambiguous signal that a package
intends it to be interpreted as a valid SPDX identifier, without the need
for complex and potentially erroneous heuristics, and allows tools to
easily and unambiguously detect invalid content.</p>
<p>This avoids both false positive (<code class="docutils literal notranslate"><span class="pre">License</span></code> values that a package author
didnt explicitly intend as an explicit SPDX identifier, but that happen
to validate as one), and false negatives (expressions the author intended
to be valid SPDX, but due to a typo or mistake are not), which are otherwise
not clearly distinguishable from true positives and negatives, an ambiguity
at odds with the goals of this PEP.</p>
<p>Furthermore, it allows both the existing <code class="docutils literal notranslate"><span class="pre">License</span></code> field and
the license classifiers to be more easily deprecated,
with tools able to cleanly distinguish between packages intending to
affirmatively conform to the updated specification in this PEP or not,
and adapt their behavior (warnings, errors, etc) accordingly.
Otherwise, tools would either have to allow duplicative and potentially
conflicting <code class="docutils literal notranslate"><span class="pre">License</span></code> fields and classifiers, or warn/error on the
substantial number of existing packages that have SPDX identifiers as the
value for the <code class="docutils literal notranslate"><span class="pre">License</span></code> field, intentionally or otherwise (e.g. <code class="docutils literal notranslate"><span class="pre">MIT</span></code>).</p>
<p>Finally, it avoids changing the behavior of an existing metadata field,
and avoids tools having to guess the <code class="docutils literal notranslate"><span class="pre">Metadata-Version</span></code> and field behavior
based on its value rather than merely its presence.</p>
<p>While this would mean the subset of existing distributions containing
<code class="docutils literal notranslate"><span class="pre">License</span></code> fields valid as SPDX license expressions wouldnt automatically be
recognized as such, this only requires appending a few characters to the key
name in the projects source metadata, and this PEP provides extensive
guidance on how this can be done automatically by tooling.</p>
<p>Given all this, it was decided to proceed with defining a new,
purpose-created field, <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code>.</p>
</section>
<section id="re-use-the-license-field-with-a-value-prefix">
<h4><a class="toc-backref" href="#re-use-the-license-field-with-a-value-prefix" role="doc-backlink">Re-Use the <code class="docutils literal notranslate"><span class="pre">License</span></code> field with a value prefix</a></h4>
<p>As an alternative to the previous, prefixing SPDX license expressions with,
e.g. <code class="docutils literal notranslate"><span class="pre">spdx:</span></code> was suggested to reduce the ambiguity inherent in re-using
the <code class="docutils literal notranslate"><span class="pre">License</span></code> field. However, this effectively amounted to creating
a field within a field, and doesnt address all the downsides of
keeping the <code class="docutils literal notranslate"><span class="pre">License</span></code> field. Namely, it still changes the behavior of an
existing metadata field, requires tools to parse its value
to determine how to handle its content, and makes the specification and
deprecation process more complex and less clean.</p>
<p>Yet, it still shares a same main potential downside as just creating a new
field: projects currently using valid SPDX identifiers in the <code class="docutils literal notranslate"><span class="pre">License</span></code>
field, intentionally or not, wont be automatically recognized, and requires
about the same amount of effort to fix, namely changing a line in the
projects source metadata. Therefore, it was rejected in favor of a new field.</p>
</section>
<section id="don-t-make-license-expression-mutually-exclusive">
<h4><a class="toc-backref" href="#don-t-make-license-expression-mutually-exclusive" role="doc-backlink">Dont make <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> mutually exclusive</a></h4>
<p>For backwards compatibility, the <code class="docutils literal notranslate"><span class="pre">License</span></code> field and/or the license
classifiers could still be allowed together with the new
<code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field, presumably with a warning. However, this
could easily lead to inconsistent, and at the very least duplicative
license metadata in no less than <em>three</em> different fields, which is
squarely contrary to the goals of this PEP of making the licensing story
simpler and unambiguous. Therefore, and in concert with clear community
consensus otherwise, this idea was soundly rejected.</p>
</section>
<section id="don-t-deprecate-existing-license-field-and-classifiers">
<h4><a class="toc-backref" href="#don-t-deprecate-existing-license-field-and-classifiers" role="doc-backlink">Dont deprecate existing <code class="docutils literal notranslate"><span class="pre">License</span></code> field and classifiers</a></h4>
<p>Several community members were initially concerned that deprecating the
existing <code class="docutils literal notranslate"><span class="pre">License</span></code> field and classifiers would result in
excessive churn for existing package authors and raise the barrier to
entry for new ones, particularly everyday Python developers seeking to
package and publish their personal projects without necessarily caring
too much about the legal technicalities or being a “license lawyer”.
Indeed, every deprecation comes with some non-zero short-term cost,
and should be carefully considered relative to the overall long-term
net benefit. And at the minimum, this change shouldnt make it more
difficult for the average Python developer to share their work under
a license of their choice, and ideally improve the situation.</p>
<p>Following many rounds of proposals, discussion and refinement,
the general consensus was clearly in favor of deprecating the legacy
means of specifying a license, in favor of “one obvious way to do it”,
to improve the currently complex and fragmented story around license
documentation. Not doing so would leave three different un-deprecated ways of
specifying a license for a package, two of them ambiguous, less than
clear/obvious how to use, inconsistently documented and out of date.
This is more complex for all tools in the ecosystem to support
indefinitely (rather than simply installers supporting older packages
implementing previous frozen metadata versions), resulting in a non-trivial
and unbounded maintenance cost.</p>
<p>Furthermore, it leads to a more complex and confusing landscape for users with
three similar but distinct options to choose from, particularly with older
documentation, answers and articles floating around suggesting different ones.
Of the three, <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> is the simplest and clearest to use
correctly; users just paste in their desired license identifier, or select it
via a tool, and theyre done; no need to learn about Trove classifiers and
dig through the list to figure out which one(s) apply (and be confused
by many ambiguous options), or figure out on their own what should go
in the <code class="docutils literal notranslate"><span class="pre">license</span></code> key (anything from nothing, to the license text,
to a free-form description, to the same SPDX identifier they would be
entering in the <code class="docutils literal notranslate"><span class="pre">license</span></code> key anyway, assuming they can
easily find documentation at all about it). In fact, this can be
made even easier thanks to the new field. For example, GitHubs popular
<a class="reference external" href="https://choosealicense.com/">ChooseALicense.com</a> links to how to add SPDX license
identifiers to the project source metadata of various languages that support
them right in the sidebar of every license page; the SPDX support in this
PEP enables adding Python to that list.</p>
<p>For current package maintainers who have specified a <code class="docutils literal notranslate"><span class="pre">License</span></code> or license
classifiers, this PEP only recommends warnings and prohibits errors for
all but publishing tools, which are allowed to error if their intended
distribution platform(s) so requires. Once maintainers are ready to
upgrade, for those already using SPDX license expressions (accidentally or not)
this only requires appending a few characters to the key name in the
projects source metadata, and for those with license classifiers that
map to a single unambiguous license, or another defined case (public domain,
proprietary), they merely need to drop the classifier and paste in the
corresponding license identifier. This PEP provides extensive guidance and
examples, as will other resources, as well as explicit instructions for
automated tooling to take care of this with no human changes needed.
More complex cases where license metadata is currently specified may
need a bit of human intervention, but in most cases tools will be able
to provide a list of options following the mappings in this PEP, and
these are typically the projects most likely to be constrained by the
limitations of the existing license metadata, and thus most benefited
by the new fields in this PEP.</p>
<p>Finally, for unmaintained packages, those using tools supporting older
metadata versions, or those who choose not to provide license metadata,
no changes are required regardless of the deprecation.</p>
</section>
<section id="don-t-mandate-validating-new-fields-on-pypi">
<h4><a class="toc-backref" href="#don-t-mandate-validating-new-fields-on-pypi" role="doc-backlink">Dont mandate validating new fields on PyPI</a></h4>
<p>Previously, while this PEP did include normative guidelines for packaging
publishing tools (such as Twine), it did not provide specific guidance
for PyPI (or other package indices) as to whether and how they
should validate the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> or <code class="docutils literal notranslate"><span class="pre">License-File</span></code> fields,
nor how they should handle using them in combination with the deprecated
<code class="docutils literal notranslate"><span class="pre">License</span></code> field or license classifiers. This simplifies the specification
and either defers implementation on PyPI to a later PEP, or gives
discretion to PyPI to enforce the stated invariants, to minimize
disruption to package authors.</p>
<p>However, this had been left unstated from before the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code>
field was separate from the existing <code class="docutils literal notranslate"><span class="pre">License</span></code>, which would make
validation much more challenging and backwards-incompatible, breaking
existing packages. With that change, there was a clear consensus that
the new field should be validated from the start, guaranteeing that all
distributions uploaded to PyPI that declare core metadata version 2.4
or higher and have the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field will have a valid
expression, such that PyPI and consumers of its packages and metadata
can rely upon to follow the specification here.</p>
<p>The same can be extended to the new <code class="docutils literal notranslate"><span class="pre">License-File</span></code> field as well,
to ensure that it is valid and the legally required license files are
present, and thus it is lawful for PyPI, users and downstream consumers
to distribute the package. (Of course, this makes no <em>guarantee</em> of such
as it is ultimately reliant on authors to declare them, but it improves
assurance of this and allows doing so in the future if the community so
decides.) To be clear, this would not require that any uploaded distribution
have such metadata, only that if they choose to declare it per the new
specification in this PEP, it is assured to be valid.</p>
</section>
</section>
<section id="source-metadata-license-key">
<h3><a class="toc-backref" href="#source-metadata-license-key" role="doc-backlink">Source metadata <code class="docutils literal notranslate"><span class="pre">license</span></code> key</a></h3>
<p>Alternate possibilities related to 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> project source metadata.</p>
<section id="add-expression-and-files-subkeys-to-table">
<h4><a class="toc-backref" href="#add-expression-and-files-subkeys-to-table" role="doc-backlink">Add <code class="docutils literal notranslate"><span class="pre">expression</span></code> and <code class="docutils literal notranslate"><span class="pre">files</span></code> subkeys to table</a></h4>
<p>A previous working draft of this PEP added <code class="docutils literal notranslate"><span class="pre">expression</span></code> and <code class="docutils literal notranslate"><span class="pre">files</span></code> subkeys
to the existing <code class="docutils literal notranslate"><span class="pre">license</span></code> table in the project source metadata, to parallel
the existing <code class="docutils literal notranslate"><span class="pre">file</span></code> and <code class="docutils literal notranslate"><span class="pre">text</span></code> subkeys. While this seemed perhaps the
most obvious approach at first glance, it had several serious drawbacks
relative to that ultimately taken here.</p>
<p>Most saliently, this means two very different types of metadata are being
specified under the same top-level key that require very different handling,
and furthermore, unlike the previous arrangement, the subkeys were not mutually
exclusive and can both be specified at once, and with some subkeys potentially
being dynamic and others static, and mapping to different core metadata fields.</p>
<p>Furthermore, this leads to a conflict with marking the key as <code class="docutils literal notranslate"><span class="pre">dynamic</span></code>
(assuming that is intended to specify the <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table keys,
as that PEP seems to imprecisely imply,
rather than core metadata fields), as either or both would have
to be treated as <code class="docutils literal notranslate"><span class="pre">dynamic</span></code>.
Grouping both license expressions and license files under the same key
forces an “all or nothing” approach, and creates ambiguity as to user intent.</p>
<p>There are further downsides to this as well. Both users and tools would need to
keep track of which fields are mutually exclusive with which of the others,
greatly increasing cognitive and code complexity, and in turn the probability
of errors. Conceptually, juxtaposing so many different fields under the
same key is rather jarring, and leads to a much more complex mapping between
<code class="docutils literal notranslate"><span class="pre">[project]</span></code> keys and core metadata fields, not in keeping with <a class="pep reference internal" href="../pep-0621/" title="PEP 621 Storing project metadata in pyproject.toml">PEP 621</a>.
This causes the <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table naming and structure to diverge further
from both the core metadata and native formats of the various popular packaging
tools that use it. Finally, this results in the spec being significantly more
complex and convoluted to understand and implement than the alternatives.</p>
<p>The approach this PEP now takes, using the reserved top-level string value
of the <code class="docutils literal notranslate"><span class="pre">license</span></code> key, adding a new <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key
and deprecating the <code class="docutils literal notranslate"><span class="pre">license</span></code> 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>),
avoids most of the issues identified above,
and results in a much clearer and cleaner design overall.
It allows <code class="docutils literal notranslate"><span class="pre">license</span></code> and <code class="docutils literal notranslate"><span class="pre">license-files</span></code> to be tagged
<code class="docutils literal notranslate"><span class="pre">dynamic</span></code> independently, separates two independent types of metadata
(syntactically and semantically), restores a closer to 1:1 mapping of
<code class="docutils literal notranslate"><span class="pre">[project]</span></code> table keys to core metadata fields,
and reduces nesting by a level for both.
Other than adding one extra key to the file, there was no significant
apparent downside to this latter approach, so it was adopted for this PEP.</p>
</section>
<section id="add-an-expression-subkey-instead-of-a-string-value">
<h4><a class="toc-backref" href="#add-an-expression-subkey-instead-of-a-string-value" role="doc-backlink">Add an <code class="docutils literal notranslate"><span class="pre">expression</span></code> subkey instead of a string value</a></h4>
<p>Adding just an <code class="docutils literal notranslate"><span class="pre">expression</span></code> subkey to the <code class="docutils literal notranslate"><span class="pre">license</span></code> table,
instead of using the reserved top-level string value,
would be more explicit for readers and writers,
in line with this PEPs goals.
However, it still has the downsides listed above
that are not specific to the inclusion of the <code class="docutils literal notranslate"><span class="pre">files</span></code> key.</p>
<p>Relative to a flat string value,
it adds verbosity, complexity and an extra level of nesting,
and requires users and tools to remember and handle
the mutual exclusivity of the subkeys
and remember which are deprecated and which are not,
instead of cleanly deprecating the table subkeys as a whole.
Furthermore, it is less clearly the “default” choice for modern use,
given users tend to gravitate toward the simplest and most obvious option.
Finally, it seems reasonable to follow the suggested guidance in <a class="pep reference internal" href="../pep-0621/" title="PEP 621 Storing project metadata in pyproject.toml">PEP 621</a>,
given the top-level string value was specifically reserved for this purpose.</p>
</section>
<section id="define-a-new-top-level-license-expression-key">
<h4><a class="toc-backref" href="#define-a-new-top-level-license-expression-key" role="doc-backlink">Define a new top-level <code class="docutils literal notranslate"><span class="pre">license-expression</span></code> key</a></h4>
<p>An earlier version of this PEP defined a new, top-level <code class="docutils literal notranslate"><span class="pre">license-expression</span></code>
under the <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table,
rather than using the reserved string value of the <code class="docutils literal notranslate"><span class="pre">license</span></code> key.
This was seen as clearer and more explicit for readers and writers,
in line with the goals of this PEP.</p>
<p>Additionally, while differences from existing tool formats (and core metadata
field names) have precedent in <a class="pep reference internal" href="../pep-0621/" title="PEP 621 Storing project metadata in pyproject.toml">PEP 621</a>,
using a key with an identical name as in most/all current tools
to mean something different (and map to a different core metadata field),
with distinct and incompatible syntax and semantics, does not,
and could cause confusion and ambiguity for readers and authors.</p>
<p>Also, per the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/declaring-project-metadata/#dynamic">project source metadata spec</a>,
this would allow separately marking the <code class="docutils literal notranslate"><span class="pre">[project]</span></code> keys
corresponding to the <code class="docutils literal notranslate"><span class="pre">License</span></code> and <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> metadata fields
as <code class="docutils literal notranslate"><span class="pre">dynamic</span></code>,
avoiding a potential concern with back-filling the <code class="docutils literal notranslate"><span class="pre">License</span></code> field
from the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field as this PEP currently allows
without it as <code class="docutils literal notranslate"><span class="pre">license</span></code> as dynamic
(which would not be possible, since they both map to the same top-level key).</p>
<p>However, community consensus favored using
the top-level string value of the existing <code class="docutils literal notranslate"><span class="pre">license</span></code> key,
as <a class="pep reference internal" href="../pep-0621/#license" title="PEP 621 Storing project metadata in pyproject.toml § license">reserved for this purpose by PEP 621</a>:</p>
<blockquote>
<div>A practical string value for the license key has been purposefully left
out to allow for a future PEP to specify support for SPDX expressions
(the same logic applies to any sort of “type” field specifying what
license the file or text represents).</div></blockquote>
<p>This is shorter and simpler for users to remember and type,
avoids adding a new top-level key while taking advantage of an existing one,
guides users toward using a license expression as the default,
and follows what was envisioned in the original <a class="pep reference internal" href="../pep-0621/" title="PEP 621 Storing project metadata in pyproject.toml">PEP 621</a>.</p>
<p>Additionally, this allows cleanly deprecating the table values
without deprecating the key itself,
and makes them inherently mutually exclusive without users having to remember
and tools having to enforce it.</p>
<p>Finally, consistency with other tool formats and the underlying core metadata
was not considered a sufficient priority
to override the advantages of using the existing key,
and the <code class="docutils literal notranslate"><span class="pre">dynamic</span></code> concerns were mostly mitigated by
not specifying legacy license to license expression conversion at build time,
explicitly specifying backfilling the <code class="docutils literal notranslate"><span class="pre">License</span></code> field when not <code class="docutils literal notranslate"><span class="pre">dynamic</span></code>,
and the fact that both fields are mutually exclusive,
so there is little practical need to distinguish which is dynamic.</p>
<p>Therefore, a top-level string value for <code class="docutils literal notranslate"><span class="pre">license</span></code> was adopted for this PEP,
as an earlier working draft had temporarily specified.</p>
</section>
<section id="add-a-type-key-to-treat-text-as-expression">
<h4><a class="toc-backref" href="#add-a-type-key-to-treat-text-as-expression" role="doc-backlink">Add a <code class="docutils literal notranslate"><span class="pre">type</span></code> key to treat <code class="docutils literal notranslate"><span class="pre">text</span></code> as expression</a></h4>
<p>Instead of using the reserved top-level string value
of 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,
one could add a <code class="docutils literal notranslate"><span class="pre">type</span></code> subkey to the <code class="docutils literal notranslate"><span class="pre">license</span></code> table
to control whether <code class="docutils literal notranslate"><span class="pre">text</span></code> (or a string value)
is interpreted as free-text or a license expression. This could make
backward compatibility a little more seamless, as older tools could ignore
it and always treat <code class="docutils literal notranslate"><span class="pre">text</span></code> as <code class="docutils literal notranslate"><span class="pre">license</span></code>, while newer tools would
know to treat it as a license expression, if <code class="docutils literal notranslate"><span class="pre">type</span></code> was set appropriately.
Indeed, <a class="pep reference internal" href="../pep-0621/" title="PEP 621 Storing project metadata in pyproject.toml">PEP 621</a> seems to suggest something of this sort as a possible
alternative way that SPDX license expressions could be implemented.</p>
<p>However, all the same downsides as in the previous item apply here,
including greater complexity, a more complex mapping between the project
source metadata and core metadata and inconsistency between the presentation
in tool config, project source metadata and core metadata,
a much less clean deprecation, further bikeshedding over what to name it,
and inability to mark one but not the other as dynamic, among others.</p>
<p>In addition, while theoretically potentially a little easier in the short
term, in the long term it would mean users would always have to remember
to specify the correct <code class="docutils literal notranslate"><span class="pre">type</span></code> to ensure their license expression is
interpreted correctly, which adds work and potential for error; we could
never safety change the default while being confident that users
understand that what they are entering is unambiguously a license expression,
with all the false positive and false negative issues as above.</p>
<p>Therefore, for these as well as the same reasons this approach was rejected
for the core metadata in favor of a distinct <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field,
we similarly reject this here in favor of
the reserved string value of the <code class="docutils literal notranslate"><span class="pre">license</span></code> key.</p>
</section>
<section id="must-be-marked-dynamic-to-back-fill">
<h4><a class="toc-backref" href="#must-be-marked-dynamic-to-back-fill" role="doc-backlink">Must be marked dynamic to back-fill</a></h4>
<p>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> could be required to be
explicitly set to dynamic in order for the <code class="docutils literal notranslate"><span class="pre">License</span></code> core metadata field
to be automatically back-filled from
the top-level string value of the <code class="docutils literal notranslate"><span class="pre">license</span></code> key.
This would be more explicit that the filling will be done,
as strictly speaking the <code class="docutils literal notranslate"><span class="pre">license</span></code> key is not (and cannot be) specified in
<code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>, and satisfies a stricter interpretation of the letter
of the previous <a class="pep reference internal" href="../pep-0621/" title="PEP 621 Storing project metadata in pyproject.toml">PEP 621</a> specification that this PEP revises.</p>
<p>However, this doesnt seem to be necessary, because it is simply using the
static, verbatim literal value of the <code class="docutils literal notranslate"><span class="pre">license</span></code> key, as specified
strictly in this PEP. Therefore, any conforming tool can trivially,
deterministically and unambiguously derive this using only the static data
in the <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> file itself.</p>
<p>Furthermore, this actually adds significant ambiguity, as it means the value
could get filled arbitrarily by other tools, which would in turn compromise
and conflict with the value of the new <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field, which is
why such is explicitly prohibited by this PEP. Therefore, not marking it as
<code class="docutils literal notranslate"><span class="pre">dynamic</span></code> will ensure it is only handled in accordance with this PEPs
requirements.</p>
<p>Finally, users explicitly being told to mark it as <code class="docutils literal notranslate"><span class="pre">dynamic</span></code>, or not, to
control filling behavior seems to be a bit of a mis-use of the <code class="docutils literal notranslate"><span class="pre">dynamic</span></code>
field as apparently intended, and prevents tools from adapting to best
practices (fill, dont fill, etc) as they develop and evolve over time.</p>
</section>
</section>
<section id="source-metadata-license-files-key">
<h3><a class="toc-backref" href="#source-metadata-license-files-key" role="doc-backlink">Source metadata <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key</a></h3>
<p>Alternatives considered for the <code class="docutils literal notranslate"><span class="pre">license-files</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, primarily related to the
path/glob type handling.</p>
<section id="add-a-type-subkey-to-license-files">
<h4><a class="toc-backref" href="#add-a-type-subkey-to-license-files" role="doc-backlink">Add a <code class="docutils literal notranslate"><span class="pre">type</span></code> subkey to <code class="docutils literal notranslate"><span class="pre">license-files</span></code></a></h4>
<p>Instead of defining mutually exclusive <code class="docutils literal notranslate"><span class="pre">paths</span></code> and <code class="docutils literal notranslate"><span class="pre">globs</span></code> subkeys
of the <code class="docutils literal notranslate"><span class="pre">license-files</span></code> <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table key, we could
achieve the same effect with a <code class="docutils literal notranslate"><span class="pre">files</span></code> subkey for the list and
a <code class="docutils literal notranslate"><span class="pre">type</span></code> subkey for how to interpret it. However, the latter offers no
real advantage over the former, in exchange for requiring more keystrokes,
verbosity and complexity, as well as less flexibility in allowing both,
or another additional subkey in the future, as well as the need to bikeshed
over the subkey name. Therefore, it was summarily rejected.</p>
</section>
<section id="only-accept-verbatim-paths">
<h4><a class="toc-backref" href="#only-accept-verbatim-paths" role="doc-backlink">Only accept verbatim paths</a></h4>
<p>Globs could be disallowed completely as values to the <code class="docutils literal notranslate"><span class="pre">license-files</span></code>
key in <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> and only verbatim literal paths allowed.
This would ensure that all license files are explicitly specified, all
specified license files are found and included, and the source metadata
is completely static in the strictest sense of the term, without tools
having to inspect the rest of the project source files to determine exactly
what license files will be included and what the <code class="docutils literal notranslate"><span class="pre">License-File</span></code> values
will be. This would also modestly simplify the spec and tool implementation.</p>
<p>However, practicality once again beats purity here. Globs are supported and
used by many existing tools for finding license files, and explicitly
specifying the full path to every license file would be unnecessarily tedious
for more complex projects with vendored code and dependencies. More
critically, it would make it much easier to accidentally miss a required
legal file, silently rendering the package illegal to distribute.</p>
<p>Tools can still statically and consistently determine the files to be included,
based only on those glob patterns the user explicitly specified and the
filenames in the package, without installing it, executing its code or even
examining its files. Furthermore, tools are still explicitly allowed to warn
if specified glob patterns (including full paths) dont match any files.
And, of course, sdists, wheels and others will have the full static list
of files specified in their distribution metadata.</p>
<p>Perhaps most importantly, this would also preclude the currently specified
default value, as widely used by the current most popular tools, and thus
be a major break to backward compatibility, tool consistency, and safe
and sane default functionality to avoid unintentional license violations.
And of course, authors are welcome and encouraged to specify their license
files explicitly via the <code class="docutils literal notranslate"><span class="pre">paths</span></code> table subkey, once they are aware of it and
if it is suitable for their project and workflow.</p>
</section>
<section id="only-accept-glob-patterns">
<h4><a class="toc-backref" href="#only-accept-glob-patterns" role="doc-backlink">Only accept glob patterns</a></h4>
<p>Conversely, all <code class="docutils literal notranslate"><span class="pre">license-files</span></code> strings could be treated as glob patterns.
This would slightly simplify the spec and implementation, avoid an extra level
of nesting, and more closely match the configuration format of existing tools.</p>
<p>However, for the cost of a few characters, it ensures users are aware
whether they are entering globs or verbatim paths. Furthermore, allowing
license files to be specified as literal paths avoids edge cases, such as those
containing glob characters (or those confusingly or even maliciously similar
to them, as described in <a class="pep reference internal" href="../pep-0672/" title="PEP 672 Unicode-related Security Considerations for Python">PEP 672</a>).</p>
<p>Including an explicit <code class="docutils literal notranslate"><span class="pre">paths</span></code> value ensures that the resulting
<code class="docutils literal notranslate"><span class="pre">License-File</span></code> metadata is correct, complete and purely static in the
strictest sense of the term, with all license paths explicitly specified
in the <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> file, guaranteed to be included and with an early
error should any be missing. This is not practical to do, at least without
serious limitations for many workflows, if we must assume the items
are glob patterns rather than literal paths.</p>
<p>This allows tools to locate them and know the exact values of the
<code class="docutils literal notranslate"><span class="pre">License-File</span></code> core metadata fields without having to traverse the
source tree of the project and match globs, potentially allowing easier,
more efficient and reliable programmatic inspection and processing.</p>
<p>Therefore, given the relatively small cost and the significant benefits,
this approach was not adopted.</p>
</section>
<section id="infer-whether-paths-or-globs">
<h4><a class="toc-backref" href="#infer-whether-paths-or-globs" role="doc-backlink">Infer whether paths or globs</a></h4>
<p>It was considered whether to simply allow specifying an array of strings
directly for the <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key, rather than making it a table with
explicit <code class="docutils literal notranslate"><span class="pre">paths</span></code> and <code class="docutils literal notranslate"><span class="pre">globs</span></code>. This would be somewhat simpler and avoid
an extra level of nesting, and more closely match the configuration format
of existing tools. However, it was ultimately rejected in favor of separate,
mutually exclusive <code class="docutils literal notranslate"><span class="pre">paths</span></code> and <code class="docutils literal notranslate"><span class="pre">globs</span></code> table subkeys.</p>
<p>In practice, it only saves six extra characters in the <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>
(<code class="docutils literal notranslate"><span class="pre">license-files</span> <span class="pre">=</span> <span class="pre">[...]</span></code> vs <code class="docutils literal notranslate"><span class="pre">license-files.globs</span> <span class="pre">=</span> <span class="pre">[...]</span></code>), but allows
the user to more explicitly declare their intent, ensures they understand how
the values are going to be interpreted, and serves as an unambiguous indicator
for tools to parse them as globs rather than verbatim path literals.</p>
<p>This, in turn, allows for more appropriate, clearly specified tool
behaviors for each case, many of which would be unreliable or impossible
without it, to avoid common traps, provide more helpful feedback and
behave more sensibly and intuitively overall. These include, with <code class="docutils literal notranslate"><span class="pre">paths</span></code>,
guaranteeing that each and every specified file is included and immediately
raising an error if one is missing, and with <code class="docutils literal notranslate"><span class="pre">globs</span></code>, checking glob syntax,
excluding unwanted backup, temporary, or other such files (as current tools
already do), and optionally warning if a glob doesnt match any files.
This also avoids edge cases (e.g. paths that contain glob characters) and
reliance on heuristics to determine interpretation—the very thing this PEP
seeks to avoid.</p>
</section>
<section id="also-allow-a-flat-array-value">
<span id="license-files-allow-flat-array"></span><h4><a class="toc-backref" href="#also-allow-a-flat-array-value" role="doc-backlink">Also allow a flat array value</a></h4>
<p>Initially, after deciding to define <code class="docutils literal notranslate"><span class="pre">license-files</span></code> as a table of <code class="docutils literal notranslate"><span class="pre">paths</span></code>
and <code class="docutils literal notranslate"><span class="pre">globs</span></code>, thought was given to making a top-level string array under the
<code class="docutils literal notranslate"><span class="pre">license-files</span></code> key mean one or the other (probably <code class="docutils literal notranslate"><span class="pre">globs</span></code>, to match most
current tools). This is slightly shorter and simpler, would allow gently
nudging users toward a preferred one, and allow a slightly cleaner handling of
the empty case (which, at present, is treated identically for either).</p>
<p>However, this again only saves six characters in the best case, and there
isnt an obvious choice; whether from a perspective of preference (both had
clear use cases and benefits), nor as to which one users would naturally
assume.</p>
<p>Flat may be better than nested, but in the face of ambiguity, users
may not resist the temptation to guess. Requiring users to explicitly specify
one or the other ensures they are aware of how their inputs will be handled,
and is more readable for others, both human and machine alike. It also makes
the spec and tool implementation slightly more complicated, and it can always
be added in the future, but not removed without breaking backward
compatibility. And finally, for the “preferred” option, it means there is
more than one obvious way to do it.</p>
<p>Therefore, per <a class="pep reference internal" href="../pep-0020/" title="PEP 20 The Zen of Python">PEP 20</a>, the Zen of Python, this approach is hereby rejected.</p>
</section>
<section id="allow-both-paths-and-globs-subkeys">
<h4><a class="toc-backref" href="#allow-both-paths-and-globs-subkeys" role="doc-backlink">Allow both <code class="docutils literal notranslate"><span class="pre">paths</span></code> and <code class="docutils literal notranslate"><span class="pre">globs</span></code> subkeys</a></h4>
<p>Allowing both <code class="docutils literal notranslate"><span class="pre">paths</span></code> and <code class="docutils literal notranslate"><span class="pre">globs</span></code> subkeys to be specified under the
<code class="docutils literal notranslate"><span class="pre">license-files</span></code> table was considered, as it could potentially allow
more flexible handling for particularly complex projects, and specify on a
per-pattern rather than overall basis whether <code class="docutils literal notranslate"><span class="pre">license-files</span></code> entries
should be treated as <code class="docutils literal notranslate"><span class="pre">paths</span></code> or <code class="docutils literal notranslate"><span class="pre">globs</span></code>.</p>
<p>However, given the existing proposed approach already matches or exceeds the
power and capabilities of those offered in tools config files, there isnt
clear demand for this and few likely cases that would benefit, it adds a large
amount of complexity for relatively minimal gain, in terms of the
specification, in tool implementations and in <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> itself.</p>
<p>There would be many more edge cases to deal with, such as how to handle files
matched by both lists, and it conflicts in multiple places with the current
specification for how tools should behave with one or the other, such as when
no files match, guarantees of all files being included and of the file paths
being explicitly, statically specified, and others.</p>
<p>Like the previous, if there is a clear need for it, it can be always allowed
in the future in a backward-compatible manner (to the extent it is possible
in the first place), while the same is not true of disallowing it.
Therefore, it was decided to require the two subkeys to be mutually exclusive.</p>
</section>
<section id="rename-paths-subkey-to-files">
<h4><a class="toc-backref" href="#rename-paths-subkey-to-files" role="doc-backlink">Rename <code class="docutils literal notranslate"><span class="pre">paths</span></code> subkey to <code class="docutils literal notranslate"><span class="pre">files</span></code></a></h4>
<p>Initially, it was considered whether to name the <code class="docutils literal notranslate"><span class="pre">paths</span></code> subkey of the
<code class="docutils literal notranslate"><span class="pre">license-files</span></code> table <code class="docutils literal notranslate"><span class="pre">files</span></code> instead. However, <code class="docutils literal notranslate"><span class="pre">paths</span></code> was ultimately
chosen, as calling the table subkey <code class="docutils literal notranslate"><span class="pre">files</span></code> resulted in duplication between
the table name (<code class="docutils literal notranslate"><span class="pre">license-files</span></code>) and the subkey name (<code class="docutils literal notranslate"><span class="pre">files</span></code>), i.e.
<code class="docutils literal notranslate"><span class="pre">license-files.files</span> <span class="pre">=</span> <span class="pre">[&quot;LICENSE.txt&quot;]</span></code>, made it seem like the preferred/
default subkey when it was not, and lacked the same parallelism with <code class="docutils literal notranslate"><span class="pre">globs</span></code>
in describing the format of the string entry rather than what was being
pointed to.</p>
</section>
<section id="must-be-marked-dynamic-to-use-defaults">
<h4><a class="toc-backref" href="#must-be-marked-dynamic-to-use-defaults" role="doc-backlink">Must be marked dynamic to use defaults</a></h4>
<p>It may seem outwardly sensible, at least with a particularly restrictive
interpretation of <a class="pep reference internal" href="../pep-0621/" title="PEP 621 Storing project metadata in pyproject.toml">PEP 621</a>s description of the <code class="docutils literal notranslate"><span class="pre">dynamic</span></code> list, to
consider requiring the <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key to be explicitly marked as
<code class="docutils literal notranslate"><span class="pre">dynamic</span></code> in order for the default glob patterns to be used, or alternatively
for license files to be matched and included at all.</p>
<p>However, this is merely declaring a static, strictly-specified default value
for this particular key, required to be used exactly by all conforming tools
(so long as it is not marked <code class="docutils literal notranslate"><span class="pre">dynamic</span></code>, negating this argument entirely),
and is no less static than any other set of glob patterns the user themself
may specify. Furthermore, the resulting <code class="docutils literal notranslate"><span class="pre">License-File</span></code> core metadata values
can still be determined with only a list of files in the source, without
installing or executing any of the code, or even inspecting file contents.</p>
<p>Moreover, even if this were not so, practicality would trump purity, as this
interpretation would be strictly backwards-incompatible with the existing
format, and be inconsistent with the behavior with the existing tools.
Further, this would create a very serious and likely risk of a large number of
projects unknowingly no longer including legally mandatory license files,
making their distribution technically illegal, and is thus not a sane,
much less sensible default.</p>
<p>Finally, aside from adding an additional line of default-required boilerplate
to the file, not defining the default as dynamic allows authors to clearly
and unambiguously indicate when their build/packaging tools are going to be
handling the inclusion of license files themselves rather than strictly
conforming to the project source metadata portions of this PEP;
to do otherwise would defeat the primary purpose of the <code class="docutils literal notranslate"><span class="pre">dynamic</span></code> list
as a marker and escape hatch.</p>
</section>
</section>
<section id="license-file-paths">
<h3><a class="toc-backref" href="#license-file-paths" role="doc-backlink">License file paths</a></h3>
<p>Alternatives related to the paths and locations of license files in the source
and built distributions.</p>
<section id="flatten-license-files-in-subdirectories">
<h4><a class="toc-backref" href="#flatten-license-files-in-subdirectories" role="doc-backlink">Flatten license files in subdirectories</a></h4>
<p>Previous drafts of this PEP were silent on the issue of handling license files
in subdirectories. Currently, the <a class="reference external" href="https://github.com/pypa/wheel/issues/138">Wheel</a> and (following its
example) <a class="reference external" href="https://github.com/pypa/setuptools/issues/2739">Setuptools</a> projects flatten all license files
into the <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directory without preserving the source subdirectory
hierarchy.</p>
<p>While this is the simplest approach and matches existing ad hoc practice,
this can result in name conflicts and license files clobbering others,
with no obvious defined behavior for how to resolve them, and leaving the
package legally un-distributable without any clear indication to users that
their specified license files have not been included.</p>
<p>Furthermore, this leads to inconsistent relative file paths for non-root
license files between the source, sdist and wheel, and prevents the paths
given in the “static” <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table metadata from being truly static,
as they need to be flattened, and may potentially overwrite one another.
Finally, the source directory structure often implies valuable information
about what the licenses apply to, and where to find them in the source,
which is lost when flattening them and far from trivial to reconstruct.</p>
<p>To resolve this, the PEP now proposes, as did contributors on both of the
above issues, reproducing the source directory structure of the original
license files inside the <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directory. This would fully resolve the
concerns above, with the only downside being a more nested <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code>
directory. There is still a risk of collision with edge-case custom
filenames (e.g. <code class="docutils literal notranslate"><span class="pre">RECORD</span></code>, <code class="docutils literal notranslate"><span class="pre">METADATA</span></code>), but that is also the case
with the previous approach, and in fact with fewer files flattened
into the root, this would actually reduce the risk. Furthermore,
the following proposal rooting the license files under a <code class="docutils literal notranslate"><span class="pre">licenses</span></code>
subdirectory eliminates both collisions and the clutter problem entirely.</p>
</section>
<section id="resolve-name-conflicts-differently">
<h4><a class="toc-backref" href="#resolve-name-conflicts-differently" role="doc-backlink">Resolve name conflicts differently</a></h4>
<p>Rather than preserving the source directory structure for license files
inside the <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directory, we could specify some other mechanism
for conflict resolution, such as pre- or appending the parent directory name
to the license filename, traversing up the tree until the name was unique,
to avoid excessively nested directories.</p>
<p>However, this would not address the path consistency issues, would require
much more discussion, coordination and bikeshedding, and further complicate
the specification and the implementations. Therefore, it was rejected in
favor of the simpler and more obvious solution of just preserving the
source subdirectory layout, as many stakeholders have already advocated for.</p>
</section>
<section id="dump-directly-in-dist-info">
<h4><a class="toc-backref" href="#dump-directly-in-dist-info" role="doc-backlink">Dump directly in <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code></a></h4>
<p>Previously, the included license files were stored directly in the top-level
<code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directory of built wheels and installed projects. This followed
existing ad hoc practice, ensured most existing wheels currently using this
feature will match new ones, and kept the specification simpler, with the
license files always being stored in the same location relative to the core
metadata regardless of distribution type.</p>
<p>However, this leads to a more cluttered <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directory, littered
with arbitrary license files and subdirectories, as opposed to separating
licenses into their own namespace (which per the Zen of Python, <a class="pep reference internal" href="../pep-0020/" title="PEP 20 The Zen of Python">PEP 20</a>, are
“one honking great idea”). While currently small, there is still a
risk of collision with specific custom license filenames
(e.g. <code class="docutils literal notranslate"><span class="pre">RECORD</span></code>, <code class="docutils literal notranslate"><span class="pre">METADATA</span></code>) in the <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directory, which
would only increase if and when additional files were specified here, and
would require carefully limiting the potential filenames used to avoid
likely conflicts with those of license-related files. Finally,
putting licenses into their own specified subdirectory would allow
humans and tools to quickly, easily and correctly list, copy and manipulate
all of them at once (such as in distro packaging, legal checks, etc)
without having to reference each of their paths from the core metadata.</p>
<p>Therefore, now is a prudent time to specify an alternate approach.
The simplest and most obvious solution, as suggested by several on the Wheel
and Setuptools implementation issues, is to simply root the license files
relative to a <code class="docutils literal notranslate"><span class="pre">licenses</span></code> subdirectory of <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code>. This is simple
to implement and solves all the problems noted here, without clear significant
drawbacks relative to other more complex options.</p>
<p>It does make the specification a bit more complex and less elegant, but
implementation should remain equally simple. It does mean that wheels
produced with following this change will have differently-located licenses
than those prior, but as this was already true for those in subdirectories,
and until this PEP there was no way of discovering these files or
accessing them programmatically, this doesnt seem likely to pose
significant problems in practice. Given this will be much harder if not
impossible to change later, once the status quo is standardized, tools are
relying on the current behavior and there is much greater uptake of not
only simply including license files but potentially accessing them as well
using the core metadata, if were going to change it, now would be the time
(particularly since were already introducing an edge-case change with how
license files in subdirs are handled, along with other refinements).</p>
<p>Therefore, the latter has been incorporated into current drafts of this PEP.</p>
</section>
<section id="add-new-licenses-category-to-wheel">
<h4><a class="toc-backref" href="#add-new-licenses-category-to-wheel" role="doc-backlink">Add new <code class="docutils literal notranslate"><span class="pre">licenses</span></code> category to wheel</a></h4>
<p>Instead of defining a root license directory (<code class="docutils literal notranslate"><span class="pre">licenses</span></code>) inside
the core metadata directory (<code class="docutils literal notranslate"><span class="pre">.dist-info</span></code>) for wheels, we could instead
define a new category (and, presumably, a corresponding install scheme),
similar to the others currently included under <code class="docutils literal notranslate"><span class="pre">.data</span></code> in the wheel archive,
specifically for license files, called (e.g.) <code class="docutils literal notranslate"><span class="pre">licenses</span></code>. This was mentioned
by the wheel creator, and would allow installing licenses somewhere more
platform-appropriate and flexible than just the <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directory
in the site path, and potentially be conceptually cleaner than including
them there.</p>
<p>However, at present, this PEP does not implement this idea, and it is
deferred to a future one. It would add significant complexity and friction
to this PEP, being primarily concerned with standardizing existing practice
and updating the core metadata specification. Furthermore, doing so would
likely require modifying <code class="docutils literal notranslate"><span class="pre">sysconfig</span></code> and the install schemes specified
therein, alongside Wheel, Installer and other tools, which would be a
non-trivial undertaking. While potentially slightly more complex for
repackagers (such as those for Linux distributions), the current proposal still
ensures all license files are included, and in a single dedicated directory
(which can easily be copied or relocated downstream), and thus should still
greatly improve the status quo in this regard without the attendant complexity.</p>
<p>In addition, this approach is not fully backwards compatible (since it
isnt transparent to tools that simply extract the wheel), is a greater
departure from existing practice and would lead to more inconsistent
license install locations from wheels of different versions. Finally,
this would mean licenses would not be installed as proximately to their
associated code, there would be more variability in the license root path
across platforms and between built distributions and installed projects,
accessing installed licenses programmatically would be more difficult, and a
suitable install location and method would need to be created, discussed
and decided that would avoid name clashes.</p>
<p>Therefore, to keep this PEP in scope, the current approach was retained.</p>
</section>
<section id="name-the-subdirectory-license-files">
<h4><a class="toc-backref" href="#name-the-subdirectory-license-files" role="doc-backlink">Name the subdirectory <code class="docutils literal notranslate"><span class="pre">license_files</span></code></a></h4>
<p>Both <code class="docutils literal notranslate"><span class="pre">licenses</span></code> and <code class="docutils literal notranslate"><span class="pre">license_files</span></code> have been suggested as potential
names for the root license directory inside <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> of wheels and
installed projects. An initial draft of the PEP specified the former
due to being slightly clearer and consistent with the
name of the core metadata field (<code class="docutils literal notranslate"><span class="pre">License-File</span></code>)
and the <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table key (<code class="docutils literal notranslate"><span class="pre">license-files</span></code>).
However, the current version of the PEP adopts the <code class="docutils literal notranslate"><span class="pre">license</span></code> name,
due to a general preference by the community for its shorter length,
greater simplicity and the lack of a separator character (<code class="docutils literal notranslate"><span class="pre">_</span></code>, <code class="docutils literal notranslate"><span class="pre">-</span></code>, etc.).</p>
</section>
</section>
<section id="other-ideas">
<h3><a class="toc-backref" href="#other-ideas" role="doc-backlink">Other ideas</a></h3>
<p>Miscellaneous proposals, possibilities and discussion points that were
ultimately not adopted.</p>
<section id="map-identifiers-to-license-files">
<h4><a class="toc-backref" href="#map-identifiers-to-license-files" role="doc-backlink">Map identifiers to license files</a></h4>
<p>This would require using a mapping (as two parallel lists would be too prone to
alignment errors), which would add extra complexity to how license
are documented and add an additional nesting level.</p>
<p>A mapping would be needed, as it cannot be guaranteed that all expressions
(keys) have a single license file associated with them (e.g.
GPL with an exception may be in a single file) and that any expression
does not have more than one. (e.g. an Apache license <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code> and
its <code class="docutils literal notranslate"><span class="pre">NOTICE</span></code> file, for instance, are two distinct files).
For most common cases, a single license expression and one or more license
files would be perfectly adequate. In the rarer and more complex cases where
there are many licenses involved, authors can still safety use the fields
specified here, just with a slight loss of clarity by not specifying which
text file(s) map to which license identifier (though this should be clear in
practice given each license identifier has corresponding SPDX-registered
full license text), while not forcing the more complex data model
(a mapping) on the large majority of users who do not need or want it.</p>
<p>We could of course have a data field with multiple possible value types (its a
string, its a list, its a mapping!) but this could be a source of confusion.
This is what has been done, for instance, in npm (historically) and in Rubygems
(still today), and as result tools need to test the type of the metadata field
before using it in code, while users are confused about when to use a list or a
string. Therefore, this approach is rejected.</p>
</section>
<section id="map-identifiers-to-source-files">
<h4><a class="toc-backref" href="#map-identifiers-to-source-files" role="doc-backlink">Map identifiers to source files</a></h4>
<p>As discussed previously, file-level notices are out of scope for this PEP,
and the existing <code class="docutils literal notranslate"><span class="pre">SPDX-License-Identifier</span></code> <a class="reference external" href="https://spdx.dev/ids/">convention</a> can
already be used if this is needed without further specification here.</p>
</section>
<section id="don-t-freeze-compatibility-with-a-specific-spdx-version">
<h4><a class="toc-backref" href="#don-t-freeze-compatibility-with-a-specific-spdx-version" role="doc-backlink">Dont freeze compatibility with a specific SPDX version</a></h4>
<p>This PEP could omit specifying a specific SPDX specification version,
or one for the list of valid license identifiers, which would allow
more flexible updates as the specification evolves without another
PEP or equivalent.</p>
<p>However, serious concerns were expressed about a future SPDX update breaking
compatibility with existing expressions and identifiers, leaving current
packages with invalid metadata per the definition in this PEP. Requiring
compatibility with a specific version of these specifications here
and a PEP or similar process to update it avoids this contingency,
and follows the practice of other packaging ecosystems.</p>
<p>Therefore, it was <a class="reference external" href="https://github.com/pombredanne/spdx-pypi-pep/issues/6">decided</a> to specify a minimum version
and requires tools to be compatible with it, while still allowing updates
so long as they dont break backward compatibility. This enables
tools to immediate take advantage of improvements and accept new
licenses, but also remain backwards compatible with the version
specified here, balancing flexibility and compatibility.</p>
</section>
<section id="different-licenses-for-source-and-binary-distributions">
<span id="rejected-ideas-difference-license-source-binary"></span><h4><a class="toc-backref" href="#different-licenses-for-source-and-binary-distributions" role="doc-backlink">Different licenses for source and binary distributions</a></h4>
<p>As an additional use case, it was asked whether it was in scope for this
PEP to handle cases where the license expression for a binary distribution
(wheel) is different from that for a source distribution (sdist), such
as in cases of non-pure-Python packages that compile and bundle binaries
under different licenses than the project itself. An example cited was
<a class="reference external" href="https://pypi.org/project/torch/">PyTorch</a>, which contains CUDA from Nvidia, which is freely
distributable but not open source. <a class="reference external" href="https://github.com/numpy/numpy/issues/8689">NumPy</a> and
<a class="reference external" href="https://github.com/scipy/scipy/issues/7093">SciPy</a> also had similar issues, as reported by the
original author of this PEP and now resolved for those cases.</p>
<p>However, given the inherent complexity here and a lack of an obvious
mechanism to do so, the fact that each wheel would need its own license
information, lack of support on PyPI for exposing license info on a
per-distribution archive basis, and the relatively niche use case, it was
determined to be out of scope for this PEP, and left to a future PEP
to resolve if sufficient need and interest exists and an appropriate
mechanism can be found.</p>
</section>
</section>
</section>
<section id="open-issues">
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2>
<section id="should-the-license-field-be-back-filled-or-mutually-exclusive">
<h3><a class="toc-backref" href="#should-the-license-field-be-back-filled-or-mutually-exclusive" role="doc-backlink">Should the <code class="docutils literal notranslate"><span class="pre">License</span></code> field be back-filled, or mutually exclusive?</a></h3>
<p>At present, this PEP explicitly allows, but does not formally recommend or
require, build tools to back-fill the <code class="docutils literal notranslate"><span class="pre">License</span></code> core metadata field with
the verbatim text from the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field. This would
presumably improve backwards compatibility and was suggested
by some on the Discourse thread. On the other hand, allowing it does
increase complexity and is less of a clean, consistent separation,
preventing the <code class="docutils literal notranslate"><span class="pre">License</span></code> field from being completely mutually exclusive
with the new <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field and requiring that their values
match.</p>
<p>As such, it would be very useful to have a more concrete and specific
rationale and use cases for the back-filled data, and give fuller
consideration to any potential benefits or drawbacks of this approach,
in order to come to a final consensus on this matter that can be appropriately
justified here.</p>
<p>Therefore, is the status quo expressed here acceptable, allowing tools
leeway to decide this for themselves? Should this PEP formally recommend,
or even require, that tools back-fill this metadata (which would presumably
be reversed once a breaking revision of the metadata spec is issued)?
Or should this not be explicitly allowed, discouraged or even prohibited?</p>
</section>
<section id="should-custom-license-identifiers-be-allowed">
<h3><a class="toc-backref" href="#should-custom-license-identifiers-be-allowed" role="doc-backlink">Should custom license identifiers be allowed?</a></h3>
<p>The current version of this PEP retains the behavior of only specifying
the use of SPDX-defined license identifiers, as well as the explicitly defined
custom identifiers <code class="docutils literal notranslate"><span class="pre">LicenseRef-Public-Domain</span></code> and <code class="docutils literal notranslate"><span class="pre">LicenseRef-Proprietary</span></code>
to handle the two common cases where projects have a license, but it is not
one that has a recognized SPDX license identifier.</p>
<p>For maximum flexibility, custom <code class="docutils literal notranslate"><span class="pre">LicenseRef-&lt;CUSTOM-TEXT&gt;</span></code> license
identifiers could be allowed, which could potentially be useful for niche
cases or corporate environments where <code class="docutils literal notranslate"><span class="pre">LicenseRef-Proprietary</span></code> is not
appropriate or insufficiently specific, but relying on mainstream Python
build tooling and the <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> metadata field is still
desirable to use for this purpose.</p>
<p>This has the downsides, however, of not catching misspellings of the
canonically defined license identifiers and thus producing license metadata
that is not a valid match for what the author intended, as well as users
potentially thinking they have to prepend <code class="docutils literal notranslate"><span class="pre">LicenseRef</span></code> in front of valid
license identifiers, as there seems to be some previous confusion about.
Furthermore, this encourages the proliferation of bespoke license identifiers,
which obviates the purpose of enabling clear, unambiguous and well
understood license metadata for which this PEP was created.</p>
<p>Indeed, for niche cases that need specific, proprietary custom licenses,
they could always simply specify <code class="docutils literal notranslate"><span class="pre">LicenseRef-Proprietary</span></code>, and then
include the actual license files needed to unambiguously identify the license
regardless (if not using SPDX license identifiers) under the <code class="docutils literal notranslate"><span class="pre">License-File</span></code>
fields. Requiring standards-conforming tools to allow custom license
identifiers does not seem very useful, since standard tools will not recognize
bespoke ones or know how to treat them. By contrast, bespoke tools, which
would be required in any case to understand and act on custom identifiers,
are explicitly allowed, with good reason (thus the <code class="docutils literal notranslate"><span class="pre">SHOULD</span></code> keyword)
to not require that license identifiers conform to those listed here.
Therefore, this specification still allows such use in private corporate
environments or specific ecosystems, while avoiding the disadvantages of
imposing them on all mainstream packaging tools.</p>
<p>As an alternative, a literal <code class="docutils literal notranslate"><span class="pre">LicenseRef-Custom</span></code> identifier could be
defined, which would more explicitly indicate that the license cannot be
expressed with defined identifiers and the license text should be referenced
for details, without carrying the negative and potentially inappropriate
implications of <code class="docutils literal notranslate"><span class="pre">LicenseRef-Proprietary</span></code>. This would avoid the main
mentioned downsides (misspellings, confusion, license proliferation) of
the approve approach of allowing an arbitrary <code class="docutils literal notranslate"><span class="pre">LicenseRef</span></code>, while
addressing several of the potential theoretical scenarios cited for it.</p>
<p>On the other hand, as SPDX aims to (and generally does) encompass all
FSF-recognized “Free” and OSI-approved “Open Source” licenses,
and those sources are kept closely in sync and are now relatively stable,
anything outside those bounds would generally be covered by
<code class="docutils literal notranslate"><span class="pre">LicenseRef-Proprietary</span></code>, thus making <code class="docutils literal notranslate"><span class="pre">LicenseRef-Custom</span></code> less specific
in that regard, and somewhat redundant to it. Furthermore, it may mislead
authors of projects with complex/multiple licenses that they should use it
over specifying a license expression.</p>
<p>At present, the PEP retains the existing approach over either of these, given
the use cases and benefits were judged to be sufficiently marginal based
on the current understanding of the packaging landscape. For both these
proposals, however, if more concrete use cases emerge, this can certainly
be reconsidered, either for this current PEP or a future one (before or
in tandem with actually removing the legacy unstructured <code class="docutils literal notranslate"><span class="pre">License</span></code>
metadata field). Not defining this now enables allowing it later
(or still now, with custom packaging tools), without affecting backward
compatibility, while the same is not so if they are allowed now and later
determined to be unnecessary or too problematic in practice.</p>
</section>
</section>
<section id="appendix-examples">
<span id="examples"></span><h2><a class="toc-backref" href="#appendix-examples" role="doc-backlink">Appendix: Examples</a></h2>
<section id="basic-example">
<span id="example-basic"></span><h3><a class="toc-backref" href="#basic-example" role="doc-backlink">Basic example</a></h3>
<p>The Setuptools project itself, as of <a class="reference external" href="https://github.com/pypa/setuptools/blob/v59.1.1/setup.cfg">version 59.1.1</a>,
does not use the <code class="docutils literal notranslate"><span class="pre">License</span></code> field in its own project source metadata.
Further, it no longer explicitly specifies <code class="docutils literal notranslate"><span class="pre">license_file</span></code>/<code class="docutils literal notranslate"><span class="pre">license_files</span></code>
as it did previously, since Setuptools relies on its own automatic
inclusion of license-related files matching common patterns,
such as the <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code> file it uses.</p>
<p>It includes the following license-related metadata in its <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code>:</p>
<div class="highlight-ini notranslate"><div class="highlight"><pre><span></span><span class="k">[metadata]</span>
<span class="na">classifiers</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="na">License</span><span class="w"> </span><span class="o">:</span><span class="s">: OSI Approved :: MIT License</span>
</pre></div>
</div>
<p>The simplest migration to this PEP would consist of using this instead:</p>
<div class="highlight-ini notranslate"><div class="highlight"><pre><span></span><span class="k">[metadata]</span>
<span class="na">license_expression</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">MIT</span>
</pre></div>
</div>
<p>Or, 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>:</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>
</pre></div>
</div>
<p>The output core metadata for the distribution packages would then be:</p>
<div class="highlight-email notranslate"><div class="highlight"><pre><span></span><span class="nt">License-Expression:</span><span class="w"> </span>MIT
<span class="nt">License-File:</span><span class="w"> </span>LICENSE
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code> file would be stored at <code class="docutils literal notranslate"><span class="pre">/setuptools-${VERSION}/LICENSE</span></code>
in the sdist and <code class="docutils literal notranslate"><span class="pre">/setuptools-${VERSION}.dist-info/licenses/LICENSE</span></code>
in the wheel, and unpacked from there into the site directory (e.g.
<code class="docutils literal notranslate"><span class="pre">site-packages</span></code>) on installation; <code class="docutils literal notranslate"><span class="pre">/</span></code> is the root of the respective archive
and <code class="docutils literal notranslate"><span class="pre">${VERSION}</span></code> the version of the Setuptools release in the core metadata.</p>
</section>
<section id="advanced-example">
<span id="example-advanced"></span><h3><a class="toc-backref" href="#advanced-example" role="doc-backlink">Advanced example</a></h3>
<p>Suppose Setuptools were to include the licenses of the third-party projects
that are vendored in the <code class="docutils literal notranslate"><span class="pre">setuptools/_vendor/</span></code> and <code class="docutils literal notranslate"><span class="pre">pkg_resources/_vendor</span></code>
directories; specifically:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>packaging==21.2
pyparsing==2.2.1
ordered-set==3.1.1
more_itertools==8.8.0
</pre></div>
</div>
<p>The license expressions for these projects are:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>packaging: Apache-2.0 OR BSD-2-Clause
pyparsing: MIT
ordered-set: MIT
more_itertools: MIT
</pre></div>
</div>
<p>A comprehensive license expression covering both Setuptools
proper and its vendored dependencies would contain these metadata,
combining all the license expressions into one. Such an expression might be:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>MIT AND (Apache-2.0 OR BSD-2-Clause)
</pre></div>
</div>
<p>In addition, per the requirements of the licenses, the relevant license files
must be included in the package. Suppose the <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code> file contains the text
of the MIT license and the copyrights used by Setuptools, <code class="docutils literal notranslate"><span class="pre">pyparsing</span></code>,
<code class="docutils literal notranslate"><span class="pre">more_itertools</span></code> and <code class="docutils literal notranslate"><span class="pre">ordered-set</span></code>; and the <code class="docutils literal notranslate"><span class="pre">LICENSE*</span></code> files in the
<code class="docutils literal notranslate"><span class="pre">setuptools/_vendor/packaging/</span></code> directory contain the Apache 2.0 and
2-clause BSD license text, and the Packaging copyright statement and
<a class="reference external" href="https://github.com/pypa/packaging/blob/21.2/LICENSE">license choice notice</a>.</p>
<p>Specifically, we assume the license files are located at the following
paths in the project source tree (relative to the project root and
<code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>):</p>
<div class="highlight-ini notranslate"><div class="highlight"><pre><span></span><span class="na">LICENSE</span>
<span class="na">setuptools/_vendor/packaging/LICENSE</span>
<span class="na">setuptools/_vendor/packaging/LICENSE.APACHE</span>
<span class="na">setuptools/_vendor/packaging/LICENSE.BSD</span>
</pre></div>
</div>
<p>Putting it all together, our <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code> would be:</p>
<div class="highlight-ini notranslate"><div class="highlight"><pre><span></span><span class="k">[metadata]</span>
<span class="na">license_expression</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">MIT AND (Apache-2.0 OR BSD-2-Clause)</span>
<span class="na">license_files</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="na">LICENSE</span>
<span class="w"> </span><span class="na">setuptools/_vendor/packaging/LICENSE</span>
<span class="w"> </span><span class="na">setuptools/_vendor/packaging/LICENSE.APACHE</span>
<span class="w"> </span><span class="na">setuptools/_vendor/packaging/LICENSE.BSD</span>
</pre></div>
</div>
<p>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>, with license files
specified explicitly via the <code class="docutils literal notranslate"><span class="pre">paths</span></code> subkey, this would look like:</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 AND (Apache-2.0 OR BSD-2-Clause)&quot;</span>
<span class="n">license-files</span><span class="p">.</span><span class="n">paths</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">&quot;LICENSE&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;setuptools/_vendor/LICENSE&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;setuptools/_vendor/LICENSE.APACHE&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;setuptools/_vendor/LICENSE.BSD&quot;</span><span class="p">,</span>
<span class="p">]</span>
</pre></div>
</div>
<p>Or alternatively, matched via glob patterns, this could be:</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 AND (Apache-2.0 OR BSD-2-Clause)&quot;</span>
<span class="n">license-files</span><span class="p">.</span><span class="n">globs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">&quot;LICENSE*&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;setuptools/_vendor/LICENSE*&quot;</span><span class="p">,</span>
<span class="p">]</span>
</pre></div>
</div>
<p>With either approach, the output core metadata in the distribution
would be:</p>
<div class="highlight-email notranslate"><div class="highlight"><pre><span></span><span class="nt">License-Expression:</span><span class="w"> </span>MIT<span class="w"> </span>AND<span class="w"> </span>(Apache-2.0<span class="w"> </span>OR<span class="w"> </span>BSD-2-Clause)
<span class="nt">License-File:</span><span class="w"> </span>LICENSE
<span class="nt">License-File:</span><span class="w"> </span>setuptools/_vendor/packaging/LICENSE
<span class="nt">License-File:</span><span class="w"> </span>setuptools/_vendor/packaging/<span class="nf">LICENSE.APACHE</span>
<span class="nt">License-File:</span><span class="w"> </span>setuptools/_vendor/packaging/<span class="nf">LICENSE.BSD</span>
</pre></div>
</div>
<p>In the resulting sdist, with <code class="docutils literal notranslate"><span class="pre">/</span></code> as the root of the archive and <code class="docutils literal notranslate"><span class="pre">${VERSION}</span></code>
the version of the Setuptools release specified in the core metadata,
the license files would be located at the paths:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>/setuptools-<span class="si">${</span><span class="nv">VERSION</span><span class="si">}</span>/LICENSE
/setuptools-<span class="si">${</span><span class="nv">VERSION</span><span class="si">}</span>/setuptools/_vendor/packaging/LICENSE
/setuptools-<span class="si">${</span><span class="nv">VERSION</span><span class="si">}</span>/setuptools/_vendor/packaging/LICENSE.APACHE
/setuptools-<span class="si">${</span><span class="nv">VERSION</span><span class="si">}</span>/setuptools/_vendor/packaging/LICENSE.BSD
</pre></div>
</div>
<p>In the built wheel, with <code class="docutils literal notranslate"><span class="pre">/</span></code> being the root of the archive and
<code class="docutils literal notranslate"><span class="pre">{version}</span></code> as the previous, the license files would be stored at:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>/setuptools-<span class="si">${</span><span class="nv">VERSION</span><span class="si">}</span>.dist-info/licenses/LICENSE
/setuptools-<span class="si">${</span><span class="nv">VERSION</span><span class="si">}</span>.dist-info/licenses/setuptools/_vendor/packaging/LICENSE
/setuptools-<span class="si">${</span><span class="nv">VERSION</span><span class="si">}</span>.dist-info/licenses/setuptools/_vendor/packaging/LICENSE.APACHE
/setuptools-<span class="si">${</span><span class="nv">VERSION</span><span class="si">}</span>.dist-info/licenses/setuptools/_vendor/packaging/LICENSE.BSD
</pre></div>
</div>
<p>Finally, in the installed project, with <code class="docutils literal notranslate"><span class="pre">site-packages</span></code> being the site dir
and <code class="docutils literal notranslate"><span class="pre">{version}</span></code> as the previous, the license files would be installed to:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>site-packages/setuptools-<span class="si">${</span><span class="nv">VERSION</span><span class="si">}</span>.dist-info/licenses/LICENSE
site-packages/setuptools-<span class="si">${</span><span class="nv">VERSION</span><span class="si">}</span>.dist-info/licenses/setuptools/_vendor/packaging/LICENSE
site-packages/setuptools-<span class="si">${</span><span class="nv">VERSION</span><span class="si">}</span>.dist-info/licenses/setuptools/_vendor/packaging/LICENSE.APACHE
site-packages/setuptools-<span class="si">${</span><span class="nv">VERSION</span><span class="si">}</span>.dist-info/licenses/setuptools/_vendor/packaging/LICENSE.BSD
</pre></div>
</div>
</section>
<section id="expression-examples">
<span id="example-expression"></span><h3><a class="toc-backref" href="#expression-examples" role="doc-backlink">Expression examples</a></h3>
<p>Some additional examples of valid <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> values:</p>
<div class="highlight-email notranslate"><div class="highlight"><pre><span></span><span class="nt">License-Expression:</span><span class="w"> </span>MIT
<span class="nt">License-Expression:</span><span class="w"> </span>BSD-3-Clause
<span class="nt">License-Expression:</span><span class="w"> </span>MIT<span class="w"> </span>AND<span class="w"> </span>(Apache-2.0<span class="w"> </span>OR<span class="w"> </span>BSD-2-clause)
<span class="nt">License-Expression:</span><span class="w"> </span>MIT<span class="w"> </span>OR<span class="w"> </span><span class="nf">GPL-2.0-or-later</span><span class="w"> </span>OR<span class="w"> </span>(FSFUL<span class="w"> </span>AND<span class="w"> </span>BSD-2-Clause)
<span class="nt">License-Expression:</span><span class="w"> </span><span class="nf">GPL-3.0-only</span><span class="w"> </span>WITH<span class="w"> </span>Classpath-Exception-2.0<span class="w"> </span>OR<span class="w"> </span>BSD-3-Clause
<span class="nt">License-Expression:</span><span class="w"> </span>LicenseRef-Public-Domain<span class="w"> </span>OR<span class="w"> </span>CC0-1.0<span class="w"> </span>OR<span class="w"> </span>Unlicense
<span class="nt">License-Expression:</span><span class="w"> </span>LicenseRef-Proprietary
</pre></div>
</div>
</section>
</section>
<section id="appendix-user-scenarios">
<span id="user-scenarios"></span><h2><a class="toc-backref" href="#appendix-user-scenarios" role="doc-backlink">Appendix: User Scenarios</a></h2>
<p>The following covers the range of common use cases from a user perspective,
providing straightforward guidance for each. Do note that the following
should <strong>not</strong> be considered legal advice, and readers should consult a
licensed legal practitioner in their jurisdiction if they are unsure about
the specifics for their situation.</p>
<section id="i-have-a-private-package-that-won-t-be-distributed">
<h3><a class="toc-backref" href="#i-have-a-private-package-that-won-t-be-distributed" role="doc-backlink">I have a private package that wont be distributed</a></h3>
<p>If your package isnt shared publicly, i.e. outside your company,
organization or household, it <em>usually</em> isnt strictly necessary to include
a formal license, so you wouldnt necessarily have to do anything extra here.</p>
<p>However, it is still a good idea to include <code class="docutils literal notranslate"><span class="pre">LicenseRef-Proprietary</span></code>
as a license expression in your package configuration, and/or a
copyright statement and any legal notices in a <code class="docutils literal notranslate"><span class="pre">LICENSE.txt</span></code> file
in the root of your project directory, which will be automatically
included by packaging tools.</p>
</section>
<section id="i-just-want-to-share-my-own-work-without-legal-restrictions">
<h3><a class="toc-backref" href="#i-just-want-to-share-my-own-work-without-legal-restrictions" role="doc-backlink">I just want to share my own work without legal restrictions</a></h3>
<p>While you arent required to include a license, if you dont, no one has
<a class="reference external" href="https://choosealicense.com/no-permission/">any permission to download, use or improve your work</a>,
so thats probably the <em>opposite</em> of what you actually want.
The <a class="reference external" href="https://opensource.org/licenses/MIT">MIT license</a> is a great choice instead, as its simple,
widely used and allows anyone to do whatever they want with your work
(other than sue you, which you probably also dont want).</p>
<p>To apply it, just paste <a class="reference external" href="https://choosealicense.com/licenses/mit/">the text</a> into a file named
<code class="docutils literal notranslate"><span class="pre">LICENSE.txt</span></code> at the root of your repo, and add the year and your name to
the copyright line. Then, just add <code class="docutils literal notranslate"><span class="pre">license</span> <span class="pre">=</span> <span class="pre">&quot;MIT&quot;</span></code> under
<code class="docutils literal notranslate"><span class="pre">[project]</span></code> in your <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> if your packaging tool supports it,
or in its config file/section (e.g. Setuptools <code class="docutils literal notranslate"><span class="pre">license_expression</span> <span class="pre">=</span> <span class="pre">MIT</span></code>
under <code class="docutils literal notranslate"><span class="pre">[metadata]</span></code> in <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code>). Youre done!</p>
</section>
<section id="i-want-to-distribute-my-project-under-a-specific-license">
<h3><a class="toc-backref" href="#i-want-to-distribute-my-project-under-a-specific-license" role="doc-backlink">I want to distribute my project under a specific license</a></h3>
<p>To use a particular license, simply paste its text into a <code class="docutils literal notranslate"><span class="pre">LICENSE.txt</span></code>
file at the root of your repo, if you dont have it in a file starting with
<code class="docutils literal notranslate"><span class="pre">LICENSE</span></code> or <code class="docutils literal notranslate"><span class="pre">COPYING</span></code> already, and add
<code class="docutils literal notranslate"><span class="pre">license</span> <span class="pre">=</span> <span class="pre">&quot;LICENSE-ID&quot;</span></code> under <code class="docutils literal notranslate"><span class="pre">[project]</span></code> in your
<code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> if your packaging tool supports it, or else in its
config file (e.g. for Setuptools, <code class="docutils literal notranslate"><span class="pre">license_expression</span> <span class="pre">=</span> <span class="pre">LICENSE-ID</span></code>
under <code class="docutils literal notranslate"><span class="pre">[metadata]</span></code> in <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code>). You can find the <code class="docutils literal notranslate"><span class="pre">LICENSE-ID</span></code>
and copyable license text on sites like
<a class="reference external" href="https://choosealicense.com/licenses/">ChooseALicense</a> or <a class="reference external" href="https://spdx.org/licenses/">SPDX</a>.</p>
<p>Many popular code hosts, project templates and packaging tools can add the
license file for you, and may support the expression as well in the future.</p>
</section>
<section id="i-maintain-an-existing-package-that-s-already-licensed">
<h3><a class="toc-backref" href="#i-maintain-an-existing-package-that-s-already-licensed" role="doc-backlink">I maintain an existing package thats already licensed</a></h3>
<p>If you already have license files and metadata in your project, you
should only need to make a couple of tweaks to take advantage of the new
functionality.</p>
<p>In your project config file, enter your license expression under
<code class="docutils literal notranslate"><span class="pre">license</span></code> (<code class="docutils literal notranslate"><span class="pre">[project]</span></code> table in <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>),
<code class="docutils literal notranslate"><span class="pre">license_expression</span></code> (Setuptools <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code> / <code class="docutils literal notranslate"><span class="pre">setup.py</span></code>),
or the equivalent for your packaging tool,
and make sure to remove any legacy <code class="docutils literal notranslate"><span class="pre">license</span></code> table subkeys or
<code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span></code> classifiers. Your existing <code class="docutils literal notranslate"><span class="pre">license</span></code> value may already
be valid as one (e.g. <code class="docutils literal notranslate"><span class="pre">MIT</span></code>, <code class="docutils literal notranslate"><span class="pre">Apache-2.0</span> <span class="pre">OR</span> <span class="pre">BSD-2-Clause</span></code>, etc);
otherwise, check the <a class="reference external" href="https://spdx.org/licenses/">SPDX license list</a> for the identifier
that matches the license used in your project.</p>
<p>If your license files begin with <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code>, <code class="docutils literal notranslate"><span class="pre">COPYING</span></code>, <code class="docutils literal notranslate"><span class="pre">NOTICE</span></code> or
<code class="docutils literal notranslate"><span class="pre">AUTHORS</span></code>, or youve already configured your packaging tool to add them
(e.g. <code class="docutils literal notranslate"><span class="pre">license_files</span></code> in <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code>), you should already be good to go.
If not, make sure to list them under <code class="docutils literal notranslate"><span class="pre">license-files.paths</span></code>
or <code class="docutils literal notranslate"><span class="pre">license-files.globs</span></code> under <code class="docutils literal notranslate"><span class="pre">[project]</span></code> in <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>
(if your tool supports it), or else in your tools configuration file
(e.g. <code class="docutils literal notranslate"><span class="pre">license_files</span></code> in <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code> for Setuptools).</p>
<p>See the <a class="reference internal" href="#example-basic"><span class="std std-ref">Basic example</span></a> for a simple but complete real-world demo
of how this works in practice, including some additional technical details.
Packaging tools may support automatically converting legacy licensing
metadata; check your tools documentation for more information.</p>
</section>
<section id="my-package-includes-other-code-under-different-licenses">
<h3><a class="toc-backref" href="#my-package-includes-other-code-under-different-licenses" role="doc-backlink">My package includes other code under different licenses</a></h3>
<p>If your project includes code from others covered by different licenses,
such as vendored dependencies or files copied from other open source
software, you can construct a license expression (or have a tool
help you do so) to describe the licenses involved and the relationship
between them.</p>
<p>In short, <code class="docutils literal notranslate"><span class="pre">License-1</span> <span class="pre">AND</span> <span class="pre">License-2</span></code> mean that <em>both</em> licenses apply
to your project, or parts of it (for example, you included a file
under another license), and <code class="docutils literal notranslate"><span class="pre">License-1</span> <span class="pre">OR</span> <span class="pre">License-2</span></code> means that
<em>either</em> of the licenses can be used, at the users option (for example,
you want to allow users a choice of multiple licenses). You can use
parenthesis (<code class="docutils literal notranslate"><span class="pre">()</span></code>) for grouping to form expressions that cover even the most
complex situations.</p>
<p>In your project config file, enter your license expression under
<code class="docutils literal notranslate"><span class="pre">license</span></code> (<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>),
<code class="docutils literal notranslate"><span class="pre">license_expression</span></code> (Setuptools <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code> / <code class="docutils literal notranslate"><span class="pre">setup.py</span></code>),
or the equivalent for your packaging tool,
and make sure to remove any legacy <code class="docutils literal notranslate"><span class="pre">license</span></code> table subkeys
or <code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span></code> classifiers.</p>
<p>Also, make sure you add the full license text of all the licenses as files
somewhere in your project repository. If all of them are in the root directory
and begin with <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code>, <code class="docutils literal notranslate"><span class="pre">COPYING</span></code>, <code class="docutils literal notranslate"><span class="pre">NOTICE</span></code> or <code class="docutils literal notranslate"><span class="pre">AUTHORS</span></code>,
they will be included automatically. Otherwise, youll need to list the
relative path or glob patterns to each of them under <code class="docutils literal notranslate"><span class="pre">license-files.paths</span></code>
or <code class="docutils literal notranslate"><span class="pre">license-files.globs</span></code> under <code class="docutils literal notranslate"><span class="pre">[project]</span></code> in <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>
(if your tool supports it), or else in your tools configuration file
(e.g. <code class="docutils literal notranslate"><span class="pre">license_files</span></code> in <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code> for Setuptools).</p>
<p>As an example, if your project was licensed MIT but incorporated
a vendored dependency (say, <code class="docutils literal notranslate"><span class="pre">packaging</span></code>) that was licensed under
either Apache 2.0 or the 2-clause BSD, your license expression would
be <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>. You might have a
<code class="docutils literal notranslate"><span class="pre">LICENSE.txt</span></code> in your repo root, and a <code class="docutils literal notranslate"><span class="pre">LICENSE-APACHE.txt</span></code> and
<code class="docutils literal notranslate"><span class="pre">LICENSE-BSD.txt</span></code> in the <code class="docutils literal notranslate"><span class="pre">_vendor</span></code> subdirectory, so to include
all of them, youd specify <code class="docutils literal notranslate"><span class="pre">[&quot;LICENSE.txt&quot;,</span> <span class="pre">&quot;_vendor/packaging/LICENSE*&quot;]</span></code>
as glob patterns, or
<code class="docutils literal notranslate"><span class="pre">[&quot;LICENSE.txt&quot;,</span> <span class="pre">&quot;_vendor/LICENSE-APACHE.txt&quot;,</span> <span class="pre">&quot;_vendor/LICENSE-BSD.txt&quot;]</span></code>
as literal file paths.</p>
<p>See a fully worked out <a class="reference internal" href="#example-advanced"><span class="std std-ref">Advanced example</span></a> for a comprehensive end-to-end
application of this to a real-world complex project, with copious technical
details, and consult a <a class="reference external" href="https://github.com/david-a-wheeler/spdx-tutorial">tutorial</a> for more help and examples
using SPDX identifiers and expressions.</p>
</section>
</section>
<section id="appendix-license-documentation-in-python">
<span id="license-doc-python"></span><h2><a class="toc-backref" href="#appendix-license-documentation-in-python" role="doc-backlink">Appendix: License Documentation in Python</a></h2>
<p>There are multiple ways used or recommended to document Python project
licenses today. The most common are listed below.</p>
<section id="license-doc-core-metadata">
<span id="id13"></span><h3><a class="toc-backref" href="#license-doc-core-metadata" role="doc-backlink">Core metadata</a></h3>
<p>There are two overlapping core metadata fields to document a license: the
license <code class="docutils literal notranslate"><span class="pre">Classifier</span></code> <a class="reference external" href="https://pypi.org/classifiers">strings</a> prefixed with <code class="docutils literal notranslate"><span class="pre">License</span> <span class="pre">::</span></code>
and the <code class="docutils literal notranslate"><span class="pre">License</span></code> <a class="reference external" href="https://packaging.python.org/guides/distributing-packages-using-setuptools/#license">field</a> as free text.</p>
<p>The core metadata <code class="docutils literal notranslate"><span class="pre">License</span></code> field documentation is currently:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="gh">License</span>
<span class="gh">=======</span>
<span class="p">..</span> <span class="ow">versionadded</span><span class="p">::</span> 1.0
Text indicating the license covering the distribution where the license
is not a selection from the &quot;License&quot; Trove classifiers. See
<span class="na">:ref:</span><span class="nv">`&quot;Classifier&quot; &lt;metadata-classifier&gt;`</span> below.
This field may also be used to specify a
particular version of a license which is named via the <span class="s">``Classifier``</span>
field, or to indicate a variation or exception to such a license.
Examples<span class="se">::</span>
<span class="s"> License: This software may only be obtained by sending the</span>
<span class="s"> author a postcard, and then the user promises not</span>
<span class="s"> to redistribute it.</span>
<span class="s"> License: GPL version 3, excluding DRM provisions</span>
</pre></div>
</div>
<p>Even though there are two fields, it is at times difficult to convey anything
but simpler licensing. For instance, some classifiers lack precision
(GPL without a version) and when multiple license classifiers are
listed, it is not clear if both licenses must apply, or the user may choose
between them. Furthermore, the list of available license classifiers
is rather limited and out-of-date.</p>
</section>
<section id="setuptools-and-wheel">
<span id="license-doc-setuptools-wheel"></span><h3><a class="toc-backref" href="#setuptools-and-wheel" role="doc-backlink">Setuptools and Wheel</a></h3>
<p>Beyond a license code or qualifier, license text files are documented and
included in a built package either implicitly or explicitly,
and this is another possible source of confusion:</p>
<ul class="simple">
<li>In the <a class="reference external" href="https://github.com/pypa/setuptools/pull/1767">Setuptools</a> and <a class="reference external" href="https://github.com/pypa/wheel/blob/0.37.0/docs/user_guide.rst#including-license-files-in-the-generated-wheel-file">Wheel</a> projects,
license files are automatically added to the distribution (at their source
location in a source distribution/sdist, and in the <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code>
directory of a built wheel) if they match one of a number of common license
file name patterns (<code class="docutils literal notranslate"><span class="pre">LICEN[CS]E*</span></code>, <code class="docutils literal notranslate"><span class="pre">COPYING*</span></code>, <code class="docutils literal notranslate"><span class="pre">NOTICE*</span></code> and
<code class="docutils literal notranslate"><span class="pre">AUTHORS*</span></code>). Alternatively, a package author can specify a list of license
file paths to include in the built wheel under the <code class="docutils literal notranslate"><span class="pre">license_files</span></code> key in
the <code class="docutils literal notranslate"><span class="pre">[metadata]</span></code> section of the projects <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code>, or as an argument
to the <code class="docutils literal notranslate"><span class="pre">setuptools.setup()</span></code> function. At present, following the Wheel
projects lead, Setuptools flattens the collected license files into the
metadata directory, clobbering files with the same name, and dumps license
files directly into the top-level <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directory, but there is a
<a class="reference external" href="https://github.com/pypa/setuptools/issues/2739">desire to resolve both these issues</a>,
contingent on this PEP being accepted.</li>
<li>Both tools also support an older, singular <code class="docutils literal notranslate"><span class="pre">license_file</span></code> parameter that
allows specifying only one license file to add to the distribution, which
has been deprecated for some time but still sees <a class="reference external" href="https://github.com/pypa/pip/blob/21.3.1/setup.cfg#L114">some use</a>.</li>
<li>Following the publication of an earlier draft of this PEP, Setuptools
<a class="reference external" href="https://github.com/pypa/setuptools/pull/2645">added support</a> for <code class="docutils literal notranslate"><span class="pre">License-File</span></code> in distribution
metadata as described in this specification. This allows other tools
consuming the resulting metadata to unambiguously locate the license file(s)
for a given package.</li>
</ul>
</section>
<section id="pypa-packaging-guide-and-sample-project">
<span id="license-doc-pypug"></span><h3><a class="toc-backref" href="#pypa-packaging-guide-and-sample-project" role="doc-backlink">PyPA Packaging Guide and Sample Project</a></h3>
<p>Both the <a class="reference external" href="https://packaging.python.org/tutorials/packaging-projects/#creating-a-license">PyPA beginner packaging tutorial</a> and its more
comprehensive <a class="reference external" href="https://packaging.python.org/guides/distributing-packages-using-setuptools/#license-txt">packaging guide</a> state that it is
important that every package include a license file. They point to the
<code class="docutils literal notranslate"><span class="pre">LICENSE.txt</span></code> in the official PyPA sample project as an example, which is
<a class="reference external" href="https://github.com/pypa/sampleproject/blob/3a836905fbd687af334db16b16c37cf51dcbc99c/setup.cfg">explicitly listed</a> under the <code class="docutils literal notranslate"><span class="pre">license_files</span></code> key in
its <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code>, following existing practice formally specified by this PEP.</p>
<p>Both the <a class="reference external" href="https://packaging.python.org/tutorials/packaging-projects/#configuring-metadata">beginner packaging tutorial</a> and the
<a class="reference external" href="https://github.com/pypa/sampleproject/blob/3a836905fbd687af334db16b16c37cf51dcbc99c/setup.py#L98">sample project</a> only use classifiers to declare a
packages license, and do not include or mention the <code class="docutils literal notranslate"><span class="pre">License</span></code> field.
The <a class="reference external" href="https://packaging.python.org/guides/distributing-packages-using-setuptools/#license">full packaging guide</a> does mention this field, but
states that authors should use the license classifiers instead, unless the
project uses a non-standard license (which the guide discourages).</p>
</section>
<section id="python-source-code-files">
<span id="license-doc-source-files"></span><h3><a class="toc-backref" href="#python-source-code-files" role="doc-backlink">Python source code files</a></h3>
<p><strong>Note:</strong> Documenting licenses in source code is not in the scope of this PEP.</p>
<p>Beside using comments and/or <code class="docutils literal notranslate"><span class="pre">SPDX-License-Identifier</span></code> conventions, the
license is <a class="reference external" href="https://github.com/search?l=Python&amp;q=%22__license__%22&amp;type=Code">sometimes</a> documented in Python code files using
a “dunder” module-level constant, typically named <code class="docutils literal notranslate"><span class="pre">__license__</span></code>.</p>
<p>This convention, while perhaps somewhat antiquated, is recognized by the
built-in <code class="docutils literal notranslate"><span class="pre">help()</span></code> function and the standard <code class="docutils literal notranslate"><span class="pre">pydoc</span></code> module.
The dunder variable will show up in the <code class="docutils literal notranslate"><span class="pre">help()</span></code> DATA section for a module.</p>
</section>
<section id="other-python-packaging-tools">
<span id="license-doc-other-packaging-tools"></span><h3><a class="toc-backref" href="#other-python-packaging-tools" role="doc-backlink">Other Python packaging tools</a></h3>
<ul class="simple">
<li><a class="reference external" href="https://docs.conda.io/projects/conda-build/en/stable/resources/define-metadata.html#about-section">Conda package manifests</a> have support for <code class="docutils literal notranslate"><span class="pre">license</span></code> and
<code class="docutils literal notranslate"><span class="pre">license_file</span></code> fields, and automatically include license files
following similar naming patterns as the Wheel and Setuptools projects.</li>
<li><a class="reference external" href="https://flit.readthedocs.io/en/stable/pyproject_toml.html">Flit</a> recommends using classifiers instead of the <code class="docutils literal notranslate"><span class="pre">License</span></code>
field (per the current PyPA packaging guide).</li>
<li><a class="reference external" href="https://docs.openstack.org/pbr/latest/user/features.html">PBR</a> uses similar data as Setuptools, but always stored in
<code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code>.</li>
<li><a class="reference external" href="https://python-poetry.org/docs/pyproject/#license">Poetry</a> specifies the use of the <code class="docutils literal notranslate"><span class="pre">license</span></code> key in
<code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> with SPDX license identifiers.</li>
</ul>
</section>
</section>
<section id="appendix-license-documentation-in-other-projects">
<span id="license-doc-other-projects"></span><h2><a class="toc-backref" href="#appendix-license-documentation-in-other-projects" role="doc-backlink">Appendix: License Documentation in Other Projects</a></h2>
<p>Here is a survey of how things are done elsewhere.</p>
<section id="linux-distribution-packages">
<h3><a class="toc-backref" href="#linux-distribution-packages" role="doc-backlink">Linux distribution packages</a></h3>
<p><strong>Note:</strong> in most cases, the texts of the most common licenses are included
globally in a shared documentation directory (e.g. <code class="docutils literal notranslate"><span class="pre">/usr/share/doc</span></code>).</p>
<ul class="simple">
<li>Debian documents package licenses with
<a class="reference external" href="https://dep-team.pages.debian.net/deps/dep5/">machine readable copyright files</a>.
It defines its own license expression syntax and list of identifiers for
common licenses, both of which are closely related to those of SPDX.</li>
<li><a class="reference external" href="https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/">Fedora packages</a> specify how to include
<a class="reference external" href="https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/#_license_text">License Texts</a> and use a
<a class="reference external" href="https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/#_valid_license_short_names">License field</a> that must be filled
with appropriate short license identifier(s) from an extensive list
of <a class="reference external" href="https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses">“Good Licenses”</a>. Fedora also defines its own
license expression syntax, similar to that of SPDX.</li>
<li><a class="reference external" href="https://en.opensuse.org/openSUSE:Packaging_guidelines#Licensing">OpenSUSE packages</a> use SPDX license expressions with
SPDX license IDs and a
<a class="reference external" href="https://docs.google.com/spreadsheets/d/14AdaJ6cmU0kvQ4ulq9pWpjdZL5tkR03exRSYJmPGdfs/pub">list of additional license identifiers</a>.</li>
<li><a class="reference external" href="https://github.com/search?l=Python&amp;q=%22__license__%22&amp;type=Code">Gentoo ebuild</a> uses a <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code> variable.
This field is specified in <a class="reference external" href="https://www.gentoo.org/glep/glep-0023.html">GLEP-0023</a> and in the
<a class="reference external" href="https://devmanual.gentoo.org/general-concepts/licenses/index.html">Gentoo development manual</a>.
Gentoo also defines a list of allowed licenses and a license expression
syntax, which is rather different from SPDX.</li>
<li>The <a class="reference external" href="https://docs.freebsd.org/en/books/porters-handbook/makefiles/#licenses">FreeBSD package Makefile</a> provides <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code> and
<code class="docutils literal notranslate"><span class="pre">LICENSE_FILE</span></code> fields with a list of custom license symbols. For
non-standard licenses, FreeBSD recommends using <code class="docutils literal notranslate"><span class="pre">LICENSE=UNKNOWN</span></code> and
adding <code class="docutils literal notranslate"><span class="pre">LICENSE_NAME</span></code> and <code class="docutils literal notranslate"><span class="pre">LICENSE_TEXT</span></code> fields, as well as sophisticated
<code class="docutils literal notranslate"><span class="pre">LICENSE_PERMS</span></code> to qualify the license permissions and <code class="docutils literal notranslate"><span class="pre">LICENSE_GROUPS</span></code>
to document a license grouping. The <code class="docutils literal notranslate"><span class="pre">LICENSE_COMB</span></code> allows documenting more
than one license and how they apply together, forming a custom license
expression syntax. FreeBSD also recommends the use of
<code class="docutils literal notranslate"><span class="pre">SPDX-License-Identifier</span></code> in source code files.</li>
<li><a class="reference external" href="https://wiki.archlinux.org/title/PKGBUILD#license">Arch Linux PKGBUILD</a> defines its
<a class="reference external" href="https://archlinux.org/packages/core/any/licenses/files/">own license identifiers</a>.
The value <code class="docutils literal notranslate"><span class="pre">'unknown'</span></code> can be used if the license is not defined.</li>
<li><a class="reference external" href="https://openwrt.org/docs/guide-developer/packages#buildpackage_variables">OpenWRT ipk packages</a> use the <code class="docutils literal notranslate"><span class="pre">PKG_LICENSE</span></code> and
<code class="docutils literal notranslate"><span class="pre">PKG_LICENSE_FILES</span></code> variables and recommend the use of SPDX License
identifiers.</li>
<li><a class="reference external" href="https://github.com/NixOS/nixpkgs/blob/21.05/lib/licenses.nix">NixOS uses SPDX identifiers</a> and some extra license IDs
in its license field.</li>
<li>GNU Guix (based on NixOS) has a single License field, uses its own
<a class="reference external" href="https://git.savannah.gnu.org/cgit/guix.git/tree/guix/licenses.scm?h=v1.3.0">license symbols list</a> and specifies how to use one license or a
<a class="reference external" href="https://guix.gnu.org/manual/en/html_node/package-Reference.html#index-license_002c-of-packages">list of them</a>.</li>
<li><a class="reference external" href="https://wiki.alpinelinux.org/wiki/Creating_an_Alpine_package#license">Alpine Linux packages</a> recommend using SPDX identifiers in the
license field.</li>
</ul>
</section>
<section id="language-and-application-packages">
<h3><a class="toc-backref" href="#language-and-application-packages" role="doc-backlink">Language and application packages</a></h3>
<ul class="simple">
<li>In Java, <a class="reference external" href="https://maven.apache.org/pom.html#Licenses">Maven POM</a> defines a <code class="docutils literal notranslate"><span class="pre">licenses</span></code> XML tag with a list
of licenses, each with a name, URL, comments and “distribution” type.
This is not mandatory, and the content of each field is not specified.</li>
<li>The <a class="reference external" href="https://docs.npmjs.com/cli/v8/configuring-npm/package-json#license">JavaScript NPM package.json</a> uses a single license field with
a SPDX license expression, or the <code class="docutils literal notranslate"><span class="pre">UNLICENSED</span></code> ID if none is specified.
A license file can be referenced as an alternative using
<code class="docutils literal notranslate"><span class="pre">SEE</span> <span class="pre">LICENSE</span> <span class="pre">IN</span> <span class="pre">&lt;filename&gt;</span></code> in the single <code class="docutils literal notranslate"><span class="pre">license</span></code> field.</li>
<li><a class="reference external" href="https://guides.rubygems.org/specification-reference/#license=">Rubygems gemspec</a> specifies either a single or list of license
strings. The relationship between multiple licenses in a
list is not specified. They recommend using SPDX license identifiers.</li>
<li><a class="reference external" href="https://metacpan.org/pod/CPAN::Meta::Spec#license">CPAN Perl modules</a> use a single license field, which is either a
single or a list of strings. The relationship between the licenses in
a list is not specified. There is a list of custom license identifiers plus
these generic identifiers: <code class="docutils literal notranslate"><span class="pre">open_source</span></code>, <code class="docutils literal notranslate"><span class="pre">restricted</span></code>, <code class="docutils literal notranslate"><span class="pre">unrestricted</span></code>,
<code class="docutils literal notranslate"><span class="pre">unknown</span></code>.</li>
<li><a class="reference external" href="https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata">Rust Cargo</a> specifies the use of an SPDX license expression
(v2.1) in the <code class="docutils literal notranslate"><span class="pre">license</span></code> field. It also supports an alternative expression
syntax using slash-separated SPDX license identifiers, and there is also a
<code class="docutils literal notranslate"><span class="pre">license_file</span></code> field. The <a class="reference external" href="https://doc.rust-lang.org/cargo/reference/registries.html#publish">crates.io package registry</a>
requires that either <code class="docutils literal notranslate"><span class="pre">license</span></code> or <code class="docutils literal notranslate"><span class="pre">license_file</span></code> fields are set when
uploading a package.</li>
<li><a class="reference external" href="https://getcomposer.org/doc/04-schema.md#license">PHP composer.json</a> uses a <code class="docutils literal notranslate"><span class="pre">license</span></code> field with
an SPDX license ID or <code class="docutils literal notranslate"><span class="pre">proprietary</span></code>. The <code class="docutils literal notranslate"><span class="pre">license</span></code> field is either a
single string with resembling the SPDX license expression syntax with
<code class="docutils literal notranslate"><span class="pre">and</span></code> and <code class="docutils literal notranslate"><span class="pre">or</span></code> keywords; or is a list of strings if there is a
(disjunctive) choice of licenses.</li>
<li><a class="reference external" href="https://docs.microsoft.com/en-us/nuget/reference/nuspec#licenseurl">NuGet packages</a> previously used only a simple license URL, but
now specify using a SPDX license expression and/or the path to a license
file within the package. The NuGet.org repository states that they only
accept license expressions that are “approved by the Open Source Initiative
or the Free Software Foundation.”</li>
<li>Go language modules <code class="docutils literal notranslate"><span class="pre">go.mod</span></code> have no provision for any metadata beyond
dependencies. Licensing information is left for code authors and other
community package managers to document.</li>
<li>The <a class="reference external" href="https://flutter.dev/docs/development/packages-and-plugins/developing-packages#adding-licenses-to-the-license-file">Dart/Flutter spec</a> recommends using a single <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code>
file that should contain all the license texts, each separated by a line
with 80 hyphens.</li>
<li>The <a class="reference external" href="https://github.com/bower/spec/blob/b00c4403e22e3f6177c410ed3391b9259687e461/json.md#license">JavaScript Bower</a> <code class="docutils literal notranslate"><span class="pre">license</span></code> field is either a single string
or list of strings using either SPDX license identifiers, or a path/URL
to a license file.</li>
<li>The <a class="reference external" href="https://guides.cocoapods.org/syntax/podspec.html#license">Cocoapods podspec</a> <code class="docutils literal notranslate"><span class="pre">license</span></code> field is either a single
string, or a mapping with <code class="docutils literal notranslate"><span class="pre">type</span></code>, <code class="docutils literal notranslate"><span class="pre">file</span></code> and <code class="docutils literal notranslate"><span class="pre">text</span></code> keys.
This is mandatory unless there is a <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code>/<code class="docutils literal notranslate"><span class="pre">LICENCE</span></code> file provided.</li>
<li><a class="reference external" href="https://cabal.readthedocs.io/en/3.6/cabal-package.html?highlight=license#pkg-field-license">Haskell Cabal</a> accepts an SPDX license expression since
version 2.2. The version of the SPDX license list used is a function of
the Cabal version. The specification also provides a mapping between
legacy (pre-SPDX) and SPDX license Identifiers. Cabal also specifies a
<code class="docutils literal notranslate"><span class="pre">license-file(s)</span></code> field that lists license files to be installed with
the package.</li>
<li><a class="reference external" href="https://hex.pm/docs/publish">Erlang/Elixir mix/hex package</a> specifies a <code class="docutils literal notranslate"><span class="pre">licenses</span></code> field as a
required list of license strings, and recommends using SPDX license
identifiers.</li>
<li><a class="reference external" href="https://dub.pm/package-format-json.html#licenses">D Langanguage dub packages</a> define their own list of license
identifiers and license expression syntax, similar to the SPDX standard.</li>
<li>The <a class="reference external" href="https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Licensing">R Package DESCRIPTION</a> defines its own sophisticated license
expression syntax and list of licenses identifiers. R has a unique way of
supporting specifiers for license versions (such as <code class="docutils literal notranslate"><span class="pre">LGPL</span> <span class="pre">(&gt;=</span> <span class="pre">2.0,</span> <span class="pre">&lt;</span> <span class="pre">3)</span></code>)
in its license expression syntax.</li>
</ul>
</section>
<section id="other-ecosystems">
<h3><a class="toc-backref" href="#other-ecosystems" role="doc-backlink">Other ecosystems</a></h3>
<ul class="simple">
<li>The <code class="docutils literal notranslate"><span class="pre">SPDX-License-Identifier</span></code> <a class="reference external" href="https://spdx.dev/ids/">header</a> is a simple
convention to document the license inside a file.</li>
<li>The <a class="reference external" href="https://www.fsf.org/blogs/rms/rms-article-for-claritys-sake-please-dont-say-licensed-under-gnu-gpl-2">Free Software Foundation (FSF)</a> promotes the use of
SPDX license identifiers for clarity in the <a class="reference external" href="https://www.gnu.org/licenses/identify-licenses-clearly.html">GPL</a> and other
versioned free software licenses.</li>
<li>The Free Software Foundation Europe (FSFE) <a class="reference external" href="https://reuse.software/">REUSE project</a>
promotes using <code class="docutils literal notranslate"><span class="pre">SPDX-License-Identifier</span></code>.</li>
<li>The <a class="reference external" href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/license-rules.rst">Linux kernel</a> uses <code class="docutils literal notranslate"><span class="pre">SPDX-License-Identifier</span></code>
and parts of the FSFE REUSE conventions to document its licenses.</li>
<li><a class="reference external" href="https://www.denx.de/wiki/U-Boot/Licensing">U-Boot</a> spearheaded using <code class="docutils literal notranslate"><span class="pre">SPDX-License-Identifier</span></code> in code
and now follows the Linux approach.</li>
<li>The Apache Software Foundation projects use <a class="reference external" href="https://svn.apache.org/repos/asf/allura/doap_Allura.rdf">RDF DOAP</a> with
a single license field pointing to SPDX license identifiers.</li>
<li>The <a class="reference external" href="https://www.eclipse.org/legal/epl-2.0/faq.php">Eclipse Foundation</a> promotes using
<code class="docutils literal notranslate"><span class="pre">SPDX-license-Identifiers</span></code>.</li>
<li>The <a class="reference external" href="https://clearlydefined.io">ClearlyDefined project</a> promotes using SPDX
license identifiers and expressions to improve license clarity.</li>
<li>The <a class="reference external" href="https://github.com/aosp-mirror/platform_external_tcpdump/blob/android-platform-12.0.0_r1/MODULE_LICENSE_BSD">Android Open Source Project</a> uses <code class="docutils literal notranslate"><span class="pre">MODULE_LICENSE_XXX</span></code>
empty tag files, where <code class="docutils literal notranslate"><span class="pre">XXX</span></code> is a license code such as <code class="docutils literal notranslate"><span class="pre">BSD</span></code>, <code class="docutils literal notranslate"><span class="pre">APACHE</span></code>,
<code class="docutils literal notranslate"><span class="pre">GPL</span></code>, etc. It also uses a <code class="docutils literal notranslate"><span class="pre">NOTICE</span></code> file that contains license and
notice texts.</li>
</ul>
</section>
</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>
</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">2023-10-11 12:05:51 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></li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<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><ul>
<li><a class="reference internal" href="#mapping-license-classifiers-to-spdx-identifiers">Mapping license classifiers to SPDX identifiers</a></li>
</ul>
</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><ul>
<li><a class="reference internal" href="#core-metadata-fields">Core metadata fields</a><ul>
<li><a class="reference internal" href="#re-use-the-license-field">Re-use the <code class="docutils literal notranslate"><span class="pre">License</span></code> field</a></li>
<li><a class="reference internal" href="#re-use-the-license-field-with-a-value-prefix">Re-Use the <code class="docutils literal notranslate"><span class="pre">License</span></code> field with a value prefix</a></li>
<li><a class="reference internal" href="#don-t-make-license-expression-mutually-exclusive">Dont make <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> mutually exclusive</a></li>
<li><a class="reference internal" href="#don-t-deprecate-existing-license-field-and-classifiers">Dont deprecate existing <code class="docutils literal notranslate"><span class="pre">License</span></code> field and classifiers</a></li>
<li><a class="reference internal" href="#don-t-mandate-validating-new-fields-on-pypi">Dont mandate validating new fields on PyPI</a></li>
</ul>
</li>
<li><a class="reference internal" href="#source-metadata-license-key">Source metadata <code class="docutils literal notranslate"><span class="pre">license</span></code> key</a><ul>
<li><a class="reference internal" href="#add-expression-and-files-subkeys-to-table">Add <code class="docutils literal notranslate"><span class="pre">expression</span></code> and <code class="docutils literal notranslate"><span class="pre">files</span></code> subkeys to table</a></li>
<li><a class="reference internal" href="#add-an-expression-subkey-instead-of-a-string-value">Add an <code class="docutils literal notranslate"><span class="pre">expression</span></code> subkey instead of a string value</a></li>
<li><a class="reference internal" href="#define-a-new-top-level-license-expression-key">Define a new top-level <code class="docutils literal notranslate"><span class="pre">license-expression</span></code> key</a></li>
<li><a class="reference internal" href="#add-a-type-key-to-treat-text-as-expression">Add a <code class="docutils literal notranslate"><span class="pre">type</span></code> key to treat <code class="docutils literal notranslate"><span class="pre">text</span></code> as expression</a></li>
<li><a class="reference internal" href="#must-be-marked-dynamic-to-back-fill">Must be marked dynamic to back-fill</a></li>
</ul>
</li>
<li><a class="reference internal" href="#source-metadata-license-files-key">Source metadata <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key</a><ul>
<li><a class="reference internal" href="#add-a-type-subkey-to-license-files">Add a <code class="docutils literal notranslate"><span class="pre">type</span></code> subkey to <code class="docutils literal notranslate"><span class="pre">license-files</span></code></a></li>
<li><a class="reference internal" href="#only-accept-verbatim-paths">Only accept verbatim paths</a></li>
<li><a class="reference internal" href="#only-accept-glob-patterns">Only accept glob patterns</a></li>
<li><a class="reference internal" href="#infer-whether-paths-or-globs">Infer whether paths or globs</a></li>
<li><a class="reference internal" href="#also-allow-a-flat-array-value">Also allow a flat array value</a></li>
<li><a class="reference internal" href="#allow-both-paths-and-globs-subkeys">Allow both <code class="docutils literal notranslate"><span class="pre">paths</span></code> and <code class="docutils literal notranslate"><span class="pre">globs</span></code> subkeys</a></li>
<li><a class="reference internal" href="#rename-paths-subkey-to-files">Rename <code class="docutils literal notranslate"><span class="pre">paths</span></code> subkey to <code class="docutils literal notranslate"><span class="pre">files</span></code></a></li>
<li><a class="reference internal" href="#must-be-marked-dynamic-to-use-defaults">Must be marked dynamic to use defaults</a></li>
</ul>
</li>
<li><a class="reference internal" href="#license-file-paths">License file paths</a><ul>
<li><a class="reference internal" href="#flatten-license-files-in-subdirectories">Flatten license files in subdirectories</a></li>
<li><a class="reference internal" href="#resolve-name-conflicts-differently">Resolve name conflicts differently</a></li>
<li><a class="reference internal" href="#dump-directly-in-dist-info">Dump directly in <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code></a></li>
<li><a class="reference internal" href="#add-new-licenses-category-to-wheel">Add new <code class="docutils literal notranslate"><span class="pre">licenses</span></code> category to wheel</a></li>
<li><a class="reference internal" href="#name-the-subdirectory-license-files">Name the subdirectory <code class="docutils literal notranslate"><span class="pre">license_files</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#other-ideas">Other ideas</a><ul>
<li><a class="reference internal" href="#map-identifiers-to-license-files">Map identifiers to license files</a></li>
<li><a class="reference internal" href="#map-identifiers-to-source-files">Map identifiers to source files</a></li>
<li><a class="reference internal" href="#don-t-freeze-compatibility-with-a-specific-spdx-version">Dont freeze compatibility with a specific SPDX version</a></li>
<li><a class="reference internal" href="#different-licenses-for-source-and-binary-distributions">Different licenses for source and binary distributions</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#open-issues">Open Issues</a><ul>
<li><a class="reference internal" href="#should-the-license-field-be-back-filled-or-mutually-exclusive">Should the <code class="docutils literal notranslate"><span class="pre">License</span></code> field be back-filled, or mutually exclusive?</a></li>
<li><a class="reference internal" href="#should-custom-license-identifiers-be-allowed">Should custom license identifiers be allowed?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#appendix-examples">Appendix: Examples</a><ul>
<li><a class="reference internal" href="#basic-example">Basic example</a></li>
<li><a class="reference internal" href="#advanced-example">Advanced example</a></li>
<li><a class="reference internal" href="#expression-examples">Expression examples</a></li>
</ul>
</li>
<li><a class="reference internal" href="#appendix-user-scenarios">Appendix: User Scenarios</a><ul>
<li><a class="reference internal" href="#i-have-a-private-package-that-won-t-be-distributed">I have a private package that wont be distributed</a></li>
<li><a class="reference internal" href="#i-just-want-to-share-my-own-work-without-legal-restrictions">I just want to share my own work without legal restrictions</a></li>
<li><a class="reference internal" href="#i-want-to-distribute-my-project-under-a-specific-license">I want to distribute my project under a specific license</a></li>
<li><a class="reference internal" href="#i-maintain-an-existing-package-that-s-already-licensed">I maintain an existing package thats already licensed</a></li>
<li><a class="reference internal" href="#my-package-includes-other-code-under-different-licenses">My package includes other code under different licenses</a></li>
</ul>
</li>
<li><a class="reference internal" href="#appendix-license-documentation-in-python">Appendix: License Documentation in Python</a><ul>
<li><a class="reference internal" href="#license-doc-core-metadata">Core metadata</a></li>
<li><a class="reference internal" href="#setuptools-and-wheel">Setuptools and Wheel</a></li>
<li><a class="reference internal" href="#pypa-packaging-guide-and-sample-project">PyPA Packaging Guide and Sample Project</a></li>
<li><a class="reference internal" href="#python-source-code-files">Python source code files</a></li>
<li><a class="reference internal" href="#other-python-packaging-tools">Other Python packaging tools</a></li>
</ul>
</li>
<li><a class="reference internal" href="#appendix-license-documentation-in-other-projects">Appendix: License Documentation in Other Projects</a><ul>
<li><a class="reference internal" href="#linux-distribution-packages">Linux distribution packages</a></li>
<li><a class="reference internal" href="#language-and-application-packages">Language and application packages</a></li>
<li><a class="reference internal" href="#other-ecosystems">Other ecosystems</a></li>
</ul>
</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>