diff --git a/pep-0639.rst b/pep-0639.rst index 45d4b60ebc1..c183c17ca0e 100644 --- a/pep-0639.rst +++ b/pep-0639.rst @@ -576,30 +576,34 @@ defines how to declare a project's source metadata under a ``[project]`` table in the ``pyproject.toml`` file for build tools to consume and output distribution core metadata. -This PEP :ref:`adds <639-spec-key-license-expression>` the ``license-expression`` -key, :ref:`adds <639-spec-key-license-files>` the ``license-files`` key and -:ref:`deprecates <639-spec-key-license>` the ``license`` key. +This PEP :ref:`adds <639-spec-key-license-expression>` +a top-level string value for the ``license`` key, +:ref:`adds <639-spec-key-license-files>` the new ``license-files`` key +and :ref:`deprecates <639-spec-key-license>` +the table value for the ``license`` key +along with its corresponding table subkeys, ``text`` and ``file``. .. _639-spec-key-license-expression: -Add ``license-expression`` key -'''''''''''''''''''''''''''''' +Add string value to ``license`` key +''''''''''''''''''''''''''''''''''' -A new ``license-expression`` key is added to the ``[project]`` table, -which has a string value that is a valid SPDX license expression, +A top-level string value is defined +for the ``license`` key in the ``[project]`` table, +which specified to be a valid SPDX license expression, as :ref:`defined previously <639-license-expression-definition>`. Its value maps to the ``License-Expression`` field in the core metadata. Build tools SHOULD validate the expression as described in the -:ref:`639-spec-field-license-expression` section, outputting -an error or warning as specified. When generating the core metadata, tools -MUST perform case normalization. +:ref:`639-spec-field-license-expression` section, +outputting an error or warning as specified. +When generating the core metadata, tools MUST perform case normalization. -If the ``license-expression`` key is present and valid (and the ``license`` -key is not specified), for purposes of backward compatibility, tools MAY -back-fill the ``License`` core metadata field with the case-normalized value -of the ``license-expression`` key. +If a top-level string value for the ``license`` key is present and valid, +for purposes of backward compatibility +tools MAY back-fill the ``License`` core metadata field +with the normalized value of the ``license`` key. .. _639-spec-key-license-files: @@ -688,37 +692,39 @@ user has explicitly specified their own. .. _639-spec-key-license: -Deprecate ``license`` key -''''''''''''''''''''''''' - -The ``license`` key in the ``[project]`` table is now deprecated. -It MUST NOT be used or listed as ``dynamic`` if either of the new -``license-expression`` or ``license-files`` keys are defined, -and build tools MUST raise an error if either is the case. - -Otherwise, if the ``text`` subkey is present in the ``license`` table, tools -SHOULD issue a warning informing users it is deprecated and recommending the -``license-expression`` key instead. - -Likewise, if the ``file`` subkey is present in the ``license`` table, tools -SHOULD issue a warning informing users it is deprecated and recommending -the ``license-files`` key instead. However, if the file is present in the -source, build tools SHOULD still use it to fill the ``License-File`` field -in the core metadata, and if so, MUST include the specified file in any -distribution archives for the project. If the file does not exist at the -specified path, tools MUST NOT fill it in a ``License-File`` field, -and SHOULD raise an error or, if not, MUST issue a warning. - -For backwards compatibility, to preserve consistent behavior with current tools -and ensure that users do not unknowingly create packages that are not legally -distributable, tools MUST assume the -:ref:`specified default value <639-default-patterns>` for the -``license-files`` key and also include, in addition to a license file -specified under this ``file`` subkey, any license files that match the -specified list of patterns. +Deprecate ``license`` key table subkeys +''''''''''''''''''''''''''''''''''''''' -The ``license`` key may be removed from a new version of the specification -in a future PEP. +Table values for the ``license`` key in the ``[project]`` table, +including the ``text`` and ``file`` table subkeys, is now deprecated. +If the new ``license-files`` key is present, +build tools MUST raise an error if the ``license`` key is defined +and has a value other than a single top-level string. + +If the new ``license-files`` key is not present +and the ``text`` subkey is present in a ``license`` table, +tools SHOULD issue a warning informing users it is deprecated +and recommending a license expression as a top-level string key instead. + +Likewise, if the new ``license-files`` key is not present +and the ``file`` subkey is present in the ``license`` table, +tools SHOULD issue a warning informing users it is deprecated and recommending +the ``license-files`` key instead. + +If the specified license ``file`` is present in the source tree, +build tools SHOULD use it to fill the ``License-File`` field +in the core metadata, and MUST include the specified file +as if it were specified in a ``license-file.paths`` field. +If the file does not exist at the specified path, +tools MUST raise an informative error as previously specified. +However, tools MUST also still assume the +:ref:`specified default value <639-default-patterns>` +for the ``license-files`` key and also include, +in addition to a license file specified under the ``license.file`` subkey, +any license files that match the specified list of patterns. + +Table values for the ``license`` key MAY be removed +from a new version of the specification in a future PEP. .. _639-spec-project-formats: @@ -883,16 +889,19 @@ but SHOULD issue an informative warning when doing so. Backwards Compatibility ======================= -Adding a new, dedicated ``License-Expression`` core metadata field and -``license-expression`` key to the ``pyproject.toml`` ``[project]`` table +Adding a new, dedicated ``License-Expression`` core metadata field +and a top-level string value for the ``license`` key reserved for this purpose +in the ``pyproject.toml`` ``[project]`` table unambiguously signals support for the specification in this PEP. This avoids the risk of new tooling misinterpreting a license expression as a free-form license description or vice versa, and raises an error if and only if the user affirmatively upgrades to the latest metadata version and adds the new field/key. -The legacy ``License`` core metadata field and ``license`` project source -metadata key will be deprecated along with the license classifiers, +The legacy ``License`` core metadata field +and the ``license`` key table subkeys (``text`` and ``file``) +in the ``pyproject.toml`` ``[project]`` table +will be deprecated along with the license classifiers, retaining backwards compatibility while gently preparing users for their future removal. Such a removal would follow a suitable transition period, and be left to a future PEP and a new version of the core metadata specification. @@ -978,7 +987,7 @@ For authors still using the now-deprecated, less precise and more redundant ``License`` field or license classifiers, packaging tools will warn them and inform them of the modern replacement, ``License-Expression``. Finally, for users who may have forgotten or not be aware they need to do so, -publishing tools will gently guide them toward including ``license-expression`` +publishing tools will gently guide them toward including ``license`` and ``license-files`` in their project source metadata. Tools may also help with the conversion and suggest a license expression in @@ -1154,7 +1163,7 @@ dig through the list to figure out which one(s) apply (and be confused by many ambiguous options), or figure out on their own what should go in the ``license`` key (anything from nothing, to the license text, to a free-form description, to the same SPDX identifier they would be -entering in the ``license-expression`` key anyway, assuming they can +entering in the ``license`` key anyway, assuming they can easily find documentation at all about it). In fact, this can be made even easier thanks to the new field. For example, GitHub's popular `ChooseALicense.com `__ links to how to add SPDX license @@ -1241,20 +1250,14 @@ specified under the same top-level key that require very different handling, and furthermore, unlike the previous arrangement, the subkeys were not mutually exclusive and can both be specified at once, and with some subkeys potentially being dynamic and others static, and mapping to different core metadata fields. -This also breaks from the consensus for the core metadata fields, namely to -separate the license expression into its own explicit field. Furthermore, this leads to a conflict with marking the key as ``dynamic`` (assuming that is intended to specify the ``[project]`` table keys, as that PEP seems to imprecisely imply, rather than core metadata fields), as either both would have -to be treated as ``dynamic``. A user may want to specify the ``expression`` -key as ``dynamic``, if they intend their tooling to generate it automatically; -conversely, they may rely on their build tool to dynamically detect license -files via means outside of that strictly specified here. And indeed, current -users may mark the present ``license`` key as ``dynamic`` to automatically -fill it in the metadata. Grouping all these uses under the same key forces an -"all or nothing" approach, and creates ambiguity as to user intent. +to be treated as ``dynamic``. +Grouping both license expressions and license files under the same key +forces an "all or nothing" approach, and creates ambiguity as to user intent. There are further downsides to this as well. Both users and tools would need to keep track of which fields are mutually exclusive with which of the others, @@ -1267,108 +1270,106 @@ from both the core metadata and native formats of the various popular packaging tools that use it. Finally, this results in the spec being significantly more complex and convoluted to understand and implement than the alternatives. -The approach this PEP now takes, adding distinct ``license-expression`` and -``license-files`` keys and simply deprecating the whole ``license`` key, avoids -all the issues identified above, and results in a much clearer and cleaner -design overall. It allows ``license`` and ``license-files`` to be tagged +The approach this PEP now takes, using the reserved top-level string value +of the ``license`` key, adding a new ``license-files`` key +and deprecating the ``license`` table subkeys (``text`` and ``file``), +avoids most of the issues identified above, +and results in a much clearer and cleaner design overall. +It allows ``license`` and ``license-files`` to be tagged ``dynamic`` independently, separates two independent types of metadata (syntactically and semantically), restores a closer to 1:1 mapping of ``[project]`` table keys to core metadata fields, and reduces nesting by a level for both. -Other than adding two extra keys to the file, there was no significant +Other than adding one extra key to the file, there was no significant apparent downside to this latter approach, so it was adopted for this PEP. -Define license expression as string value -''''''''''''''''''''''''''''''''''''''''' +Add an ``expression`` subkey instead of a string value +'''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Adding just an ``expression`` subkey to the ``license`` table, +instead of using the reserved top-level string value, +would be more explicit for readers and writers, +in line with this PEP's goals. +However, it still has the downsides listed above +that are not specific to the inclusion of the ``files`` key. + +Relative to a flat string value, +it adds verbosity, complexity and an extra level of nesting, +and requires users and tools to remember and handle +the mutual exclusivity of the subkeys +and remember which are deprecated and which are not, +instead of cleanly deprecating the table subkeys as a whole. +Furthermore, it is less clearly the "default" choice for modern use, +given users tend to gravitate toward the simplest and most obvious option. +Finally, it seems reasonable to follow the suggested guidance in :pep:`621`, +given the top-level string value was specifically reserved for this purpose. + + +Define a new top-level ``license-expression`` key +''''''''''''''''''''''''''''''''''''''''''''''''' + +An earlier version of this PEP defined a new, top-level ``license-expression`` +under the ``[project]`` table, +rather than using the reserved string value of the ``license`` key. +This was seen as clearer and more explicit for readers and writers, +in line with the goals of this PEP. + +Additionally, while differences from existing tool formats (and core metadata +field names) has precedent in :pep:`621`, +using a key with an identical name as in most/all current tools +to mean something different (and map to a different core metadata field), +with distinct and incompatible syntax and semantics, does not, +and could cause confusion and ambiguity for readers and authors. + +Also, per the `project source metadata spec `__, +this would allow separately marking the ``[project]`` keys +corresponding to the ``License`` and ``License-Expression`` metadata fields +as ``dynamic``, +avoiding a potential concern with back-filling the ``License`` field +from the ``License-Expression`` field as this PEP currently allows +without it as ``license`` as dynamic +(which would not be possible, since they both map to the same top-level key). -A compromise approach between adding two new top-level keys for license -expressions and files would be adding a separate ``license-files`` key, -but re-using the ``license`` key for the license expression, either by -defining it as the (previously reserved) string value for the ``license`` -key, retaining the ``expression`` subkey in the ``license`` table, or -allowing both. Indeed, this would seem to have been envisioned by :pep:`621` -itself with this PEP in mind, in particular the first approach: +However, community consensus was in favor instead using +the top-level string value of the existing ``license`` key, +as :pep:`reserved for this purpose by PEP 621 <621#license>`: 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). -However, while a working draft temporarily explored this solution, it was -ultimately rejected, as it shared most of the downsides identified with -adding new subkeys under the existing ``license`` table, as well as several -of its own, with again minimal advantage over separating both. +This is shorter and simpler for users to remember and type, +avoids adding a new top-level key while taking advantage of an existing one, +guides users toward using a license expression as the default, +and follows what was envisioned in the original :pep:`621`. -Also, this still means that per the -`project source metadata spec `__, -it is not possible to separately mark the ``[project]`` keys -corresponding to the ``License`` and ``License-Expression`` metadata fields -as ``dynamic``. -This raises a potential concern with back-filling the ``License`` field -from the ``License-Expression`` field as this PEP currently allows -(without making an exception from strict ``dynamic`` behavior in this case), -as marking ``license`` as dynamic -would mean it cannot be specified in the ``[project]`` table at all. - -Furthermore, this would mean existing project source metadata specifying -``license`` as ``dynamic`` would be ambiguous, as it would be impossible for -tools to statically determine if they are intended to conform to previous -metadata versions specifying ``License``, or this version specifying -``License-Expression``. Tools would have no way of determining which field, -if either, might be filled in the resulting distribution's core metadata. -By contrast, the present approach makes clear what the author intended, -allows tools to unambiguously determine which field(s) may be dynamically -inserted, and ensures backward compatibility such that current project -source metadata do not unknowingly specify both the old and the new field -as dynamic, and instead must do so explicitly per :pep:`621`'s intent. +Additionally, this allows cleanly deprecating the table values +without deprecating the key itself, +and makes them inherently mutually exclusive without users having to remember +and tools having to enforce it. -Additionally, while differences from existing tool formats (and core metadata -field names) has precedent in :pep:`621` (though is best avoided if practical), -using a key with an identical name as in all current tools (and of an existing -core metadata field) to mean something different (and map to a different -core metadata field), with distinct and incompatible syntax and semantics, -does not, and is likely to create substantial and confusion and ambiguity -for readers and authors, contrary to the fundamental goals of this PEP. - -Finally, this means that the top-level ``license`` key still maps to multiple -core metadata fields with different purposes and interpretation (``License`` -and ``License-Expression``), this would deny a clear separation from the -old behavior by not cleanly deprecating the ``license`` key, and -increases the complexity of the specification and implementation. - -In addition to the aforementioned issues, this also requires deciding between -the three individual approaches (``expression`` subkey, top-level string or -allowing both), all of which have further significant downsides and none of -which are clearly superior or more obvious, leading to needless bikeshedding. - -If the license expression was made the string value of the ``license`` key, -as reserved by :pep:`621`, it would be slightly shorter for users to type and -more obviously the preferred approach. However, it is far *less* obvious that -it is a license expression at all, to authors and those viewing the files, -and this lack of clarity, explicitness, ambiguity and potential for user -confusion is exactly what this PEP seeks to avoid, all to save a few characters -over other approaches. - -If an ``expression`` subkey was added to the ``license`` table, it would retain -the clarity of a new top-level key, but add additional complexity for no -real benefit, with an extra level of nesting, and users and tools needing to -deal with the mutual exclusivity of the subkeys, as before. And allowing both -(as a table subkey *and* the string value) would inherit both's downsides, -while adding even more spec and tool complexity and making there more than -"one obvious way to do it", further potentially confusing users. - -Therefore, a separate top-level ``license-expression`` key was adopted to avoid -all these issues, with relatively minimal downside aside from adding a single -additional key and (versus some approaches) a few extra characters to type. - - -Add a ``type`` key to treat as expression -''''''''''''''''''''''''''''''''''''''''' - -Instead of creating a new top-level ``license-expression`` key in the -``[project]`` table, one could add a ``type`` subkey to the existing -``license`` table to control whether ``text`` (or a string value) +Finally, consistency with other tool formats and the underlying core metadata +was not considered a sufficient priority +to override the advantages of using the existing key, +and the ``dynamic`` concerns were mostly mitigated by +not specifying legacy license to license expression conversion at build time, +explicitly specifying backfilling the ``License`` field when not ``dynamic``, +and the fact that both fields are mutually exclusive, +so there is little practical need to distinguish which is dynamic. + +Therefore, a top-level string value for ``license`` was adopted for this PEP, +as an earlier working draft had temporarily specified. + + +Add a ``type`` key to treat ``text`` as expression +'''''''''''''''''''''''''''''''''''''''''''''''''' + +Instead of using the reserved top-level string value +of the ``license`` key in the ``[project]`` table, +one could add a ``type`` subkey to the ``license`` table +to control whether ``text`` (or a string value) is interpreted as free-text or a license expression. This could make backward compatibility a little more seamless, as older tools could ignore it and always treat ``text`` as ``license``, while newer tools would @@ -1393,7 +1394,8 @@ with all the false positive and false negative issues as above. Therefore, for these as well as the same reasons this approach was rejected for the core metadata in favor of a distinct ``License-Expression`` field, -we similarly reject this here. +we similarly reject this here in favor of +the reserved string value of the ``license`` key. Must be marked dynamic to back-fill @@ -1401,14 +1403,15 @@ Must be marked dynamic to back-fill The ``license`` key in the ``pyproject.toml`` could be required to be explicitly set to dynamic in order for the ``License`` core metadata field -to be automatically back-filled from the value of the ``license-expression`` -key. This would be more explicit that the filling will be done, as strictly -speaking the ``license`` key is not (and cannot be) specified in +to be automatically back-filled from +the top-level string value of the ``license`` key. +This would be more explicit that the filling will be done, +as strictly speaking the ``license`` key is not (and cannot be) specified in ``pyproject.toml``, and satisfies a stricter interpretation of the letter of the previous :pep:`621` specification that this PEP revises. -However, this isn't seen to be necessary, because it is simply using the -static, verbatim literal value of the ``license-expression`` key, as specified +However, this doesn't seen to be necessary, because it is simply using the +static, verbatim literal value of the ``license`` key, as specified strictly in this PEP. Therefore, any conforming tool can trivially, deterministically and unambiguously derive this using only the static data in the ``pyproject.toml`` file itself. @@ -2030,7 +2033,7 @@ Or, in the ``[project]`` table of ``pyproject.toml``: .. code-block:: toml [project] - license-expression = "MIT" + license = "MIT" The output core metadata for the distribution packages would then be: @@ -2116,7 +2119,7 @@ specified explicitly via the ``paths`` subkey, this would look like: .. code-block:: toml [project] - license-expression = "MIT AND (Apache-2.0 OR BSD-2-Clause)" + license = "MIT AND (Apache-2.0 OR BSD-2-Clause)" license-files.paths = [ "LICENSE", "setuptools/_vendor/LICENSE", @@ -2129,7 +2132,7 @@ Or alternatively, matched via glob patterns, this could be: .. code-block:: toml [project] - license-expression = "MIT AND (Apache-2.0 OR BSD-2-Clause)" + license = "MIT AND (Apache-2.0 OR BSD-2-Clause)" license-files.globs = [ "LICENSE*", "setuptools/_vendor/LICENSE*", @@ -2234,7 +2237,7 @@ widely used and allows anyone to do whatever they want with your work To apply it, just paste `the text `__ into a file named ``LICENSE.txt`` at the root of your repo, and add the year and your name to -the copyright line. Then, just add ``license-expression = "MIT"`` under +the copyright line. Then, just add ``license = "MIT"`` under ``[project]`` in your ``pyproject.toml`` if your packaging tool supports it, or in its config file/section (e.g. Setuptools ``license_expression = MIT`` under ``[metadata]`` in ``setup.cfg``). You're done! @@ -2246,7 +2249,7 @@ I want to distribute my project under a specific license To use a particular license, simply paste its text into a ``LICENSE.txt`` file at the root of your repo, if you don't have it in a file starting with ``LICENSE`` or ``COPYING`` already, and add -``license-expression = "LICENSE-ID"`` under ``[project]`` in your +``license = "LICENSE-ID"`` under ``[project]`` in your ``pyproject.toml`` if your packaging tool supports it, or else in its config file (e.g. for Setuptools, ``license_expression = LICENSE-ID`` under ``[metadata]`` in ``setup.cfg``). You can find the ``LICENSE-ID`` @@ -2265,10 +2268,10 @@ should only need to make a couple of tweaks to take advantage of the new functionality. In your project config file, enter your license expression under -``license-expression`` (``[project]`` table in ``pyproject.toml``), +``license`` (``[project]`` table in ``pyproject.toml``), ``license_expression`` (Setuptools ``setup.cfg`` / ``setup.py``), or the equivalent for your packaging tool, -and make sure to remove any legacy ``license`` value or +and make sure to remove any legacy ``license`` table subkeys or ``License ::`` classifiers. Your existing ``license`` value may already be valid as one (e.g. ``MIT``, ``Apache-2.0 OR BSD-2-Clause``, etc); otherwise, check the `SPDX license list `__ for the identifier @@ -2306,10 +2309,10 @@ parenthesis (``()``) for grouping to form expressions that cover even the most complex situations. In your project config file, enter your license expression under -``license-expression`` (``[project]`` table of ``pyproject.toml``), +``license`` (``[project]`` table of ``pyproject.toml``), ``license_expression`` (Setuptools ``setup.cfg`` / ``setup.py``), or the equivalent for your packaging tool, -and make sure to remove any legacy ``license`` value +and make sure to remove any legacy ``license`` table subkeys or ``License ::`` classifiers. Also, make sure you add the full license text of all the licenses as files @@ -2474,7 +2477,7 @@ Other Python packaging tools - `PBR `__ uses similar data as Setuptools, but always stored in ``setup.cfg``. -- `Poetry `__ specifies the use of the ``license`` field in +- `Poetry `__ specifies the use of the ``license`` key in ``pyproject.toml`` with SPDX license identifiers.