613 lines
45 KiB
HTML
613 lines
45 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>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> » </li>
|
||
<li><a href="../../pep-0000/">PEP Index</a> » </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 doesn’t 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 won’t 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
|
||
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">
|
||
<h3>Don’t 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>Don’t 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 shouldn’t 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>Don’t 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 didn’t 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">["LICEN[CS]E*",</span> <span class="pre">"COPYING*",</span> <span class="pre">"NOTICE*",</span> <span class="pre">"AUTHORS*"]</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 didn’t 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
|
||
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 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>Don’t 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 don’t 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>Don’t 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,
|
||
it’s 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 can’t 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">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-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">Don’t freeze compatibility with a specific SPDX version</a></li>
|
||
<li><a class="reference internal" href="#don-t-allow-custom-license-identifiers">Don’t 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> |