mirror of https://github.com/python/peps
2508 lines
239 KiB
HTML
2508 lines
239 KiB
HTML
|
||
<!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> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </li>
|
||
<li>PEP 639</li>
|
||
</ul>
|
||
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
|
||
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
|
||
</button>
|
||
</header>
|
||
<article>
|
||
<section id="pep-content">
|
||
<h1 class="page-title">PEP 639 – Improving License Clarity with Better Package Metadata</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Philippe Ombredanne <pombredanne at nexb.com>,
|
||
C.A.M. Gerlach <CAM.Gerlach at Gerlach.CAM></dd>
|
||
<dt class="field-even">PEP-Delegate<span class="colon">:</span></dt>
|
||
<dd class="field-even">Brett Cannon <brett at python.org></dd>
|
||
<dt class="field-odd">Discussions-To<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><a class="reference external" href="https://discuss.python.org/t/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">Don’t 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">Don’t 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">Don’t 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">Don’t 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 won’t 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 that’s 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 PEP’s 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 don’t 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 project’s license) immediately when PyPI deprecates the old ones.</p>
|
||
<p>Furthermore, this only covers simple packages entirely under a single license;
|
||
it doesn’t 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 distribution’s 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 don’t 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 project’s 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 project’s 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 file’s 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 distribution’s 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 distribution’s metadata contains no <code class="docutils literal notranslate"><span class="pre">License-File</span></code> entries,
|
||
and publishing tools MAY but build tools MUST NOT raise an error.</p>
|
||
<p>For all newly-uploaded 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 project’s source
|
||
metadata under a <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table in the <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> file 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">"LICEN[CS]E*"</span><span class="p">,</span><span class="w"> </span><span class="s2">"COPYING*"</span><span class="p">,</span><span class="w"> </span><span class="s2">"NOTICE*"</span><span class="p">,</span><span class="w"> </span><span class="s2">"AUTHORS*"</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 aren’t 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 package’s
|
||
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
|
||
didn’t 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 wouldn’t automatically be
|
||
recognized as such, this only requires appending a few characters to the key
|
||
name in the project’s 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 doesn’t 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, won’t be automatically recognized, and requires
|
||
about the same amount of effort to fix, namely changing a line in the
|
||
project’s 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">Don’t 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">Don’t 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 shouldn’t 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 they’re 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, GitHub’s 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
|
||
project’s 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">Don’t 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 PEP’s 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 doesn’t 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 PEP’s
|
||
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, don’t 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) don’t 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 doesn’t 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
|
||
isn’t 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 isn’t
|
||
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">["LICENSE.txt"]</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 doesn’t 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 we’re going to change it, now would be the time
|
||
(particularly since we’re 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
|
||
isn’t 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 (it’s a
|
||
string, it’s a list, it’s 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">Don’t 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 don’t 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-<CUSTOM-TEXT></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">"MIT"</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">"MIT AND (Apache-2.0 OR BSD-2-Clause)"</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">"LICENSE"</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">"setuptools/_vendor/LICENSE"</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">"setuptools/_vendor/LICENSE.APACHE"</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">"setuptools/_vendor/LICENSE.BSD"</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">"MIT AND (Apache-2.0 OR BSD-2-Clause)"</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">"LICENSE*"</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">"setuptools/_vendor/LICENSE*"</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 won’t be distributed</a></h3>
|
||
<p>If your package isn’t shared publicly, i.e. outside your company,
|
||
organization or household, it <em>usually</em> isn’t strictly necessary to include
|
||
a formal license, so you wouldn’t 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 aren’t required to include a license, if you don’t, no one has
|
||
<a class="reference external" href="https://choosealicense.com/no-permission/">any permission to download, use or improve your work</a>,
|
||
so that’s 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 it’s simple,
|
||
widely used and allows anyone to do whatever they want with your work
|
||
(other than sue you, which you probably also don’t 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">"MIT"</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>). You’re 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 don’t 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">"LICENSE-ID"</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 that’s 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 you’ve 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 tool’s 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 tool’s 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 user’s 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, you’ll 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 tool’s 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, you’d specify <code class="docutils literal notranslate"><span class="pre">["LICENSE.txt",</span> <span class="pre">"_vendor/packaging/LICENSE*"]</span></code>
|
||
as glob patterns, or
|
||
<code class="docutils literal notranslate"><span class="pre">["LICENSE.txt",</span> <span class="pre">"_vendor/LICENSE-APACHE.txt",</span> <span class="pre">"_vendor/LICENSE-BSD.txt"]</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 "License" Trove classifiers. See
|
||
<span class="na">:ref:</span><span class="nv">`"Classifier" <metadata-classifier>`</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 project’s <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
|
||
project’s 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
|
||
package’s 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&q=%22__license__%22&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&q=%22__license__%22&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"><filename></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">(>=</span> <span class="pre">2.0,</span> <span class="pre"><</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">Don’t 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">Don’t 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">Don’t 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">Don’t 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 won’t 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 that’s 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> |