python-peps/pep-0639/appendix-rejected-ideas/index.html

613 lines
45 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>Appendix: Rejected Ideas | peps.python.org</title>
<link rel="shortcut icon" href="../../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0639/appendix-rejected-ideas/">
<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='Appendix: Rejected Ideas | peps.python.org'>
<meta property="og:description" content="This document contains a list of the alternative ideas to the ones proposed in PEP 639 with detailed explanations why they were rejected.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0639/appendix-rejected-ideas/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This document contains a list of the alternative ideas to the ones proposed in PEP 639 with detailed explanations why they were rejected.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../../pep-0000/">PEP Index</a> &raquo; </li>
<li>Appendix: Rejected Ideas</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="appendix-rejected-ideas">
<span id="rejected-ideas-details"></span><h1>Appendix: Rejected Ideas</h1>
<section id="abstract">
<h2>Abstract</h2>
<p>This document contains a list of the alternative ideas to the ones proposed
in PEP 639 with detailed explanations why they were rejected.</p>
</section>
<section id="core-metadata-fields">
<h2>Core Metadata fields</h2>
<p>Potential alternatives to the structure, content and deprecation of the
Core Metadata fields specified in <a class="pep reference internal" href="../pep-0639/">PEP 639</a>.</p>
<section id="re-use-the-license-field">
<h3>Re-use the <code class="docutils literal notranslate"><span class="pre">License</span></code> field</h3>
<p>Following <a class="reference external" href="https://github.com/pombredanne/spdx-pypi-pep/issues/7">initial discussion</a>, earlier versions of
PEP 639 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 cause a warning and eventually it would be treated as an
error.</p>
<p>This would be more backwards-compatibile, allowed a smooth adoption
of SPDX license expressions in the community,
and avoided adding yet another license-related field.</p>
<p>Eventually, consensus was reached that a
dedicated <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> field was a better approach.
The presence of this field unambiguously signals support for the SPDX
identifiers, without the need for complex heuristics, and allows tools to
easily detect invalid content.</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 easily deprecated,
with tools able to distinguish between packages conforming to PEP 639 or not,
and adapt their behavior accordingly.</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>Distributions which already contain valid SPDX license expressions in the
<code class="docutils literal notranslate"><span class="pre">License</span></code> fields will not automatically be recognized as such.
The migration is simple though, and PEP 639 provides
guidance on how this can be done automatically by tooling.</p>
</section>
<section id="re-use-the-license-field-with-a-value-prefix">
<h3>Re-Use the <code class="docutils literal notranslate"><span class="pre">License</span></code> field with a value prefix</h3>
<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 of re-using
the <code class="docutils literal notranslate"><span class="pre">License</span></code> field. However, this effectively amounted to creating
a field within a field, and doesnt address 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>Projects currently using valid SPDX identifiers in the <code class="docutils literal notranslate"><span class="pre">License</span></code>
field wont be automatically recognized, and require
about the same amount of effort to fix as in the case of introducing a new
field, namely changing a line in the
projects source metadata. Therefore, it was rejected in favor of a new field.</p>
</section>
<section id="don-t-make-license-expression-mutually-exclusive">
<h3>Dont make <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> mutually exclusive</h3>
<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
license metadata in no less than <em>three</em> different fields, which is
contrary to the goal of PEP 639 of making the licensing story
unambiguous. Therefore, with the community
consensus this idea was rejected.</p>
</section>
<section id="don-t-deprecate-existing-license-field-and-classifiers">
<h3>Dont deprecate existing <code class="docutils literal notranslate"><span class="pre">License</span></code> field and classifiers</h3>
<p>Several community members were concerned that deprecating the
existing <code class="docutils literal notranslate"><span class="pre">License</span></code> field and classifiers would result in
much churn for package authors and raise the barrier to
entry for new ones, particularly developers seeking to
package their personal projects without caring
too much about the legal technicalities.
Indeed, every deprecation should be carefully considered relative to the
long-term
net benefit. At the minimum, this change shouldnt make it more
difficult for a Python developer to share their work under
a license of their choice, and ideally improve the situation.</p>
<p>Following many rounds of discussion,
the general consensus was in favor of deprecating the legacy
means of specifying a license and in favor of “one obvious way to do it”.
Not doing so would leave three different un-deprecated ways of
specifying a license for a package, two of them ambiguous,
inconsistently documented and out of date.
This is more complex for tools to support
indefinitely, resulting in a non-trivial maintenance cost.</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">
<h3>Dont mandate validating new fields on PyPI</h3>
<p>Previously, PEP 639 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 defers implementation on PyPI to a later PEP to minimize
disruption to package authors.</p>
<p>This was in place for an earlier draft of PEP 639 which didnt separate
<code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> from the <code class="docutils literal notranslate"><span class="pre">License</span></code> field. The validation would have
been difficult and backwards-incompatible, breaking existing packages.
With the current proposal, 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. To be clear, this would not require that any uploaded distribution
have such metadata, only that if they choose to declare it per the
specification in PEP 639, it is assured to be valid.</p>
</section>
</section>
<section id="source-metadata-license-key">
<h2>Source metadata <code class="docutils literal notranslate"><span class="pre">license</span></code> key</h2>
<p>Alternative 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-new-subkeys-to-table">
<h3>Add new subkeys to table</h3>
<p>There were proposals to add various subkeys to the table.
Combining different types of metadata which require different handling,
adding new guidance regarding the subkeys mutual exclusivity and
the possibility to define some of them as dynamic would make the
transition harder and create more confusion rather than clarity for the users.
This approach has been rejected in favour of more flat <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>
design, clear mapping between <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> keys and Core Metadata fields,
and increased readability of the separate keys.</p>
<p>Rejected proposals:</p>
<ul class="simple">
<li>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</li>
<li>add an <code class="docutils literal notranslate"><span class="pre">expression</span></code> subkey instead of a string value</li>
<li>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</li>
</ul>
</section>
<section id="define-a-new-top-level-license-expression-key">
<h3>Define a new top-level <code class="docutils literal notranslate"><span class="pre">license-expression</span></code> key</h3>
<p>An earlier version of PEP 639 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 string value of the <code class="docutils literal notranslate"><span class="pre">license</span></code> key.
This was seen as clearer for readers and writers,
in line with the goals of PEP 639.</p>
<p>While differences from existing tool formats (and Core Metadata
field names) have precedent in <a class="pep reference internal" href="../pep-0621/">PEP 621</a>, repurposing an existing key to mean
something different (and map to a different Core Metadata field),
with distinct and incompatible syntax does not,
and could cause ambiguity for readers and authors.</p>
<p>Also, per the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/pyproject-toml/#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 PEP 639 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">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 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/">PEP 621</a>.</p>
<p>Additionally, this allows cleanly deprecating the table values
without deprecating the key itself,
and makes them 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 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 PEP 639,
as an earlier working draft had temporarily specified.</p>
</section>
</section>
<section id="source-metadata-license-files-key">
<h2>Source metadata <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key</h2>
<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="define-mutually-exclusve-paths-and-globs-subkeys-to-license-files">
<h3>Define mutually exclusve <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 <code class="docutils literal notranslate"><span class="pre">license-files</span></code></h3>
<p>A previous draft of the PEP specified 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.
This was proposed to achieve the maximum clarity of the defined values for
both users and tools.
Allowing license files to be specified as literal paths would avoid edge cases,
such as those containing glob characters
(or those confusingly similar to them, as described in <a class="pep reference internal" href="../pep-0672/">PEP 672</a>).</p>
<p>However, this approach introduces an extra level of nesting - in the very same
way that PEP 639 removes from the <code class="docutils literal notranslate"><span class="pre">license</span></code> key. This creates more burden
on project authors who need to disambiguate and choose one or the other
approach to specify their license files location. It was pointed out that
it is easily possible to incorrectly assume that paths also support
globs.</p>
<p>Therefore, it was decided against this approach in favor of a flat array value
which simplifies the specification and implementation,
and more closely matches the configuration format of existing tools.
The PEP recommends not to use other than alphanumerical symbols and dot
(<code class="docutils literal notranslate"><span class="pre">.</span></code>) in the filenames to not create confusion
when interpreting glob patterns.</p>
</section>
<section id="only-accept-verbatim-paths">
<h3>Only accept verbatim paths</h3>
<p>Globs could be disallowed 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 paths allowed.
This would ensure that all license files are explicitly specified,
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 simplify the spec and tool implementation.</p>
<p>However, practicality beats purity here. Globs are already supported
by many existing tools, and explicitly
specifying the full path to every license file would be unnecessarily tedious
for complex projects with vendored dependencies. More
critically, it would make it much easier to accidentally miss a required
legal file, creating the package illegal to distribute.</p>
<p>Tools can still determine the files to be included,
based only on the glob patterns the user specified and the
filenames in the package, without installing it, executing its code or even
examining its files.
And, of course, sdists, wheels and others will have the full static list
of files specified in their distribution metadata.</p>
</section>
<section id="use-a-default-value-for-license-files-if-not-specified">
<h3>Use a default value for <code class="docutils literal notranslate"><span class="pre">license-files</span></code> if not specified</h3>
<p>A previous draft of the PEP proposed a default value for detecting
license files in case the users have not declared any and not marked the key
as dynamic.
That value was defined as an array of globs:
<code class="docutils literal notranslate"><span class="pre">[&quot;LICEN[CS]E*&quot;,</span> <span class="pre">&quot;COPYING*&quot;,</span> <span class="pre">&quot;NOTICE*&quot;,</span> <span class="pre">&quot;AUTHORS*&quot;]</span></code></p>
<p>However, this would create an exception among the existing metadata,
as no other key has got implicit defaults defined. Implicit values in
pyproject.toml keys are delegated to the <code class="docutils literal notranslate"><span class="pre">dynamic</span></code> field,
which is specified as being calculated. Also, the values were chosen
arbitrarily, without a strong justification why they should pose a standard.</p>
</section>
<section id="must-be-marked-dynamic-to-use-defaults">
<h3>Must be marked dynamic to use defaults</h3>
<p>With a restrictive
interpretation of <a class="pep reference internal" href="../pep-0621/">PEP 621</a>s description of the <code class="docutils literal notranslate"><span class="pre">dynamic</span></code> list it may
seem sensible to require the <code class="docutils literal notranslate"><span class="pre">license-files</span></code> key to be marked as
<code class="docutils literal notranslate"><span class="pre">dynamic</span></code> 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 just declaring a static, strictly-specified default value,
required to be used exactly by all conforming tools, similarly to any other set
of glob patterns the user themself may specify.
The resulting <code class="docutils literal notranslate"><span class="pre">License-File</span></code> Core Metadata values
can be determined through inspecting a list of files in the source, without
executing code, or even inspecting file contents.</p>
<p>Moreover, even if this were not so, this
interpretation would be backwards-incompatible with the existing
format, and be inconsistent with the behavior with the existing tools.
Further, this would create a serious risk of a large number of
projects unknowingly no longer including legally mandatory license files,
and is thus not a sane default.</p>
<p>Finally, not defining the default as dynamic allows authors to unambiguously
indicate when their build/packaging tools are going to be
handling the inclusion of license files themselves;
to do otherwise would defeat the purpose of the <code class="docutils literal notranslate"><span class="pre">dynamic</span></code> list.</p>
</section>
</section>
<section id="license-file-paths">
<h2>License file paths</h2>
<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">
<h3>Flatten license files in subdirectories</h3>
<p>Previous drafts of PEP 639 didnt specify how to handle the license files
in subdirectories. Currently, the <a class="reference external" href="https://github.com/pypa/wheel/issues/138">Wheel</a> and
<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 approach and matches existing ad hoc practice,
it can result in name conflicts and license files clobbering others,
with no defined behavior for how to resolve them, and leaving the
package legally un-distributable without any clear indication that
the 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.
Finally, the source directory structure often holds valuable information
about what the licenses apply to,
which is lost when flattening them and far from trivial to reconstruct.</p>
<p>To resolve this, the PEP now proposes 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. The only downside of this
approach is having a more nested <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code>
directory. The following proposal rooting the license files under a <code class="docutils literal notranslate"><span class="pre">licenses</span></code>
subdirectory eliminates both name collisions and the clutter problem entirely.</p>
</section>
<section id="resolve-name-conflicts-differently">
<h3>Resolve name conflicts differently</h3>
<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 and further complicate
the specification. Therefore, it was rejected in
favor of the more obvious solution of just preserving the
source subdirectory layout, as many stakeholders have advocated for.</p>
</section>
<section id="dump-directly-in-dist-info">
<h3>Dump directly in <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code></h3>
<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.</p>
<p>However, this leads to a more cluttered <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code> directory
as opposed to separating
licenses into their own namespace. There is still a
risk of collision with 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 require limiting the potential filenames used. Finally,
putting licenses into their own specified subdirectory would allow
humans and tools to correctly 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, the simplest and most obvious solution, as suggested by several
on the Wheel
and Setuptools implementation issues, is to 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 significant
drawbacks relative to other more complex options.</p>
<p>It does make the specification a bit more complex, 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 PEP 639 there was no way of
accessing these files programmatically, this should not pose
significant problems in practice.</p>
</section>
<section id="add-new-licenses-category-to-wheel">
<h3>Add new <code class="docutils literal notranslate"><span class="pre">licenses</span></code> category to wheel</h3>
<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.</p>
<p>However, at present, PEP 639 does not implement this idea, and it is
deferred to a future one. It would add significant complexity and friction
to PEP 639, being primarily concerned with standardizing existing practice
and updating the Core Metadata specification. Furthermore, doing so could
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, the current proposal still
ensures all license files are included in a single dedicated directory,
and thus should still
greatly improve the status quo in this regard.</p>
<p>In addition, this approach is not fully backwards compatible (since it
isnt transparent to tools that simply extract the wheel), is a greater
departure from existing practice and would lead to more inconsistent
license install locations from wheels of different versions. Finally,
this would mean licenses would not be installed as close 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 that would avoid
name clashes.</p>
<p>Therefore, to keep PEP 639 in scope, the current approach was retained.</p>
</section>
<section id="name-the-subdirectory-license-files">
<h3>Name the subdirectory <code class="docutils literal notranslate"><span class="pre">license_files</span></code></h3>
<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">licenses</span></code> name,
due to a general preference by the community for its shorter length
and the lack of a separator character.</p>
</section>
</section>
<section id="other-ideas">
<h2>Other ideas</h2>
<p>Miscellaneous proposals, possibilities and discussion points that were
ultimately not adopted.</p>
<section id="map-identifiers-to-license-files">
<h3>Map identifiers to license files</h3>
<p>This would require using a mapping, 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 safely 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 each license identifier
has corresponding SPDX-registered
full license text), while not forcing the more complex 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
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">
<h3>Map identifiers to source files</h3>
<p>As discussed previously, file-level notices are out of scope for PEP 639,
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">
<h3>Dont freeze compatibility with a specific SPDX version</h3>
<p>PEP 639 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.</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 PEP 639. 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 require tools to be compatible with it, while still allowing updates
so long as they dont break backward compatibility. This enables
tools to immediate take advantage of improvements and accept new
licenses balancing flexibility and compatibility.</p>
</section>
<section id="don-t-allow-custom-license-identifiers">
<h3>Dont allow custom license identifiers</h3>
<p>A previous draft of this PEP specified the possibility to use only two
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 cases where projects have a license, but there is not a
recognized SPDX license identifier for it.
The custom identifiers cannot be checked for correctness and users may think
they always have to prepend identifiers with <code class="docutils literal notranslate"><span class="pre">LicenseRef</span></code>.
This would lead to tools producing invalid metadata.</p>
<p>However, Python packages are produced in many open and close
environments,
where it may be impossible to declare the license using only the small subset
of the allowed custom identifiers and where, for various reasons,
its not possible to add the license to the SPDX license list.</p>
<p>The custom license identifiers are explicitly allowed and described in the
official SPDX specification and they can be syntactically validated although
not case-normalized.</p>
<p>Therefore, with acknowledgement that the custom identifiers cant be fully
validated and may contain mistakes, it was decided to allow
them in line with the official SPDX specification.</p>
</section>
<section id="different-licenses-for-source-and-binary-distributions">
<span id="rejected-ideas-difference-license-source-binary"></span><h3>Different licenses for source and binary distributions</h3>
<p>As an additional use case, it was asked whether it was in scope for
PEP 639 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.</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 PEP 639, 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>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#core-metadata-fields">Core Metadata fields</a><ul>
<li><a class="reference internal" href="#re-use-the-license-field">Re-use the <code class="docutils literal notranslate"><span class="pre">License</span></code> field</a></li>
<li><a class="reference internal" href="#re-use-the-license-field-with-a-value-prefix">Re-Use the <code class="docutils literal notranslate"><span class="pre">License</span></code> field with a value prefix</a></li>
<li><a class="reference internal" href="#don-t-make-license-expression-mutually-exclusive">Dont make <code class="docutils literal notranslate"><span class="pre">License-Expression</span></code> mutually exclusive</a></li>
<li><a class="reference internal" href="#don-t-deprecate-existing-license-field-and-classifiers">Dont deprecate existing <code class="docutils literal notranslate"><span class="pre">License</span></code> field and classifiers</a></li>
<li><a class="reference internal" href="#don-t-mandate-validating-new-fields-on-pypi">Dont mandate validating new fields on PyPI</a></li>
</ul>
</li>
<li><a class="reference internal" href="#source-metadata-license-key">Source metadata <code class="docutils literal notranslate"><span class="pre">license</span></code> key</a><ul>
<li><a class="reference internal" href="#add-new-subkeys-to-table">Add new subkeys to table</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>
</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="#define-mutually-exclusve-paths-and-globs-subkeys-to-license-files">Define mutually exclusve <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 <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="#use-a-default-value-for-license-files-if-not-specified">Use a default value for <code class="docutils literal notranslate"><span class="pre">license-files</span></code> if not specified</a></li>
<li><a class="reference internal" href="#must-be-marked-dynamic-to-use-defaults">Must be marked dynamic to use defaults</a></li>
</ul>
</li>
<li><a class="reference internal" href="#license-file-paths">License file paths</a><ul>
<li><a class="reference internal" href="#flatten-license-files-in-subdirectories">Flatten license files in subdirectories</a></li>
<li><a class="reference internal" href="#resolve-name-conflicts-differently">Resolve name conflicts differently</a></li>
<li><a class="reference internal" href="#dump-directly-in-dist-info">Dump directly in <code class="docutils literal notranslate"><span class="pre">.dist-info</span></code></a></li>
<li><a class="reference internal" href="#add-new-licenses-category-to-wheel">Add new <code class="docutils literal notranslate"><span class="pre">licenses</span></code> category to wheel</a></li>
<li><a class="reference internal" href="#name-the-subdirectory-license-files">Name the subdirectory <code class="docutils literal notranslate"><span class="pre">license_files</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#other-ideas">Other ideas</a><ul>
<li><a class="reference internal" href="#map-identifiers-to-license-files">Map identifiers to license files</a></li>
<li><a class="reference internal" href="#map-identifiers-to-source-files">Map identifiers to source files</a></li>
<li><a class="reference internal" href="#don-t-freeze-compatibility-with-a-specific-spdx-version">Dont freeze compatibility with a specific SPDX version</a></li>
<li><a class="reference internal" href="#don-t-allow-custom-license-identifiers">Dont allow custom license identifiers</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>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0639/appendix-rejected-ideas.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>