PEP 639: Clarify License-File field, slim down terminology & remove future PEPs (#2298)

* PEP 639: Remove speculative future PEPs section and cut down terminology

* PEP 639: Clarify intended role of License-File field in other formats

* PEP 639: Move User Scenarios to an appendix and de-number

* PEP 639: Apply suggestions from Adam's reivew and other refinements
This commit is contained in:
CAM Gerlach 2022-02-03 17:16:44 -06:00 committed by GitHub
parent cd4d4bbf57
commit 670de668d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 200 additions and 228 deletions

View File

@ -43,13 +43,13 @@ The PEP also:
tools converting legacy license metadata, adding license files and
validating license expressions.
- Discusses `user scenarios <User Scenarios_>`_,
describes a `reference implementation <Reference Implementation_>`_,
- Describes a `reference implementation <Reference Implementation_>`_,
analyzes numerous `potential alternatives <Rejected Ideas_>`_,
includes `detailed examples <Appendix 1. License Expression Examples_>`_ and
includes `detailed examples <Appendix: License Expression Examples_>`_,
explains `user scenarios <Appendix: User Scenarios_>`_ and
surveys license documentation
`in Python packaging <Appendix 2. License Documentation in Python_>`_ and
`other ecosystems <Appendix 3. License Documentation in Other Projects_>`_.
`in Python packaging <Appendix: License Documentation in Python_>`_ and
`other ecosystems <Appendix: License Documentation in Other Projects_>`_.
The changes in this PEP will update the
`core metadata <#coremetadataspec>`_ to version 2.3, modify the
@ -62,11 +62,11 @@ and make minor additions to the `source distribution (sdist) <#sdistspec_>`_,
Goals
=====
This PEP's scope is limited to how we document the license of a
distribution package, specifically covering:
This PEP's scope is limited to covering new mechanisms for documenting
the license of a distribution package, specifically defining:
- An improved and structured way to include a license expression.
- A formal mechanism to include license texts in a built distribution (wheel).
- A means of specifying a SPDX license expression.
- A method of including license texts in distributions and installed projects.
The changes to the core metadata specification that this PEP requires have been
designed to minimize impact and maximize backward compatibility.
@ -112,22 +112,6 @@ binary distribution packages don't have
`the same licenses <Different licenses for source and binary distributions_>`_.
Possible future PEPs
--------------------
It is the intention of the authors of this PEP to consider the submission of
related but separate PEPs in the future, which may include:
- Removing the deprecated ``License`` field and license classifiers
from the core metadata specification.
- Making the ``License-Expression`` and ``License-File`` fields mandatory
for publishing tools and PyPI packages.
- Requiring uploads to PyPI to use only Free and Open Source Software (FOSS)
licenses.
Motivation
==========
@ -161,10 +145,10 @@ Rationale
A survey of existing license metadata definitions in use in the Python
ecosystem today is provided in
`Appendix 2 <Appendix 2. License Documentation in Python_>`_ of this PEP,
`an appendix <Appendix: License Documentation in Python_>`_ of this PEP,
and license documentation in a variety of other packaging systems,
Linux distros, languages ecosystems and applications is surveyed in
`Appendix 3 <Appendix 3. License Documentation in Other Projects_>`_.
`another appendix <Appendix: License Documentation in Other Projects_>`_.
There are a few takeaways from the survey:
@ -225,45 +209,32 @@ alike.
Terminology
===========
This PEP seeks to clearly define the terms it uses, specifically those that:
This PEP seeks to clearly define the terms it uses, given that some have
multiple established meanings (e.g. import vs. distribution package,
wheel *format* vs. Wheel *project*); are related and often used
interchangeably, but have critical distinctions in meaning
(e.g. :pep:`621` *key* vs. core metadata *field*); are existing concepts
that don't have formal terms/definitions (e.g. project/source metadata vs.
distribution/built metadata, build vs. publishing tools), or are new concepts
introduced here (e.g. license expression/identifier).
- Have multiple established meanings (e.g. import vs. distribution package,
wheel *format* vs. Wheel *project*).
This PEP also uses terms defined in the
`PyPA PyPUG Glossary <#pypugglossary_>`_
(specifically *built/binary distribution*, *distribution package*,
*project* and *source distribution*), and by the `SPDX Project <#spdx_>`_
(*license identifier*, *license expression*).
- Are related and often used interchangeably, but have critical
distinctions in meaning (e.g. :pep:`621` *key* vs. core metadata *field*,
a point of apparent confusion in :pep:`621` with significant effects on this
PEP).
- Are existing concepts that don't have formal terms/definitions
(e.g. project/source metadata vs. distribution/built metadata,
build vs. publishing tools).
- Are new concepts introduced here (e.g. license expression/identifier).
Whenever available, definitions are excerpted from the
`PyPA PyPUG Glossary <#pypugglossary_>`_ and `SPDX <#spdx_>`_. Terms are listed
here in their full versions; related words (``Rel:``) are in parenthesis,
Terms are listed here in their full versions;
related words (``Rel:``) are in parenthesis,
including short forms (``Short:``), sub-terms (``Sub:``) and common synonyms
for the purposes of this PEP (``Syn:``).
**Built Distribution** *(Syn: Binary Distribution/Wheel)*
A Distribution format containing files and metadata that only need to be
moved to the correct location on the target system to be installed.
Wheel is such a format, whereas distutil's *[sic]* Source Distribution
is not.
*(PyPUG Glossary)*
For the purposes of this PEP, except where noted, this is synonymous
with **binary distribution** (a built distribution containing compiled code)
and **wheel** (the format).
**Core Metadata** *(Syn: Package Metadata, Sub: Distribution Metadata)*
The `PyPA specification <#coremetadataspec_>`_ and the set of metadata fields
it defines that describe key static attributes of distribution packages
and installed projects.
**Distribution metadata** refers to, more specifically, the concrete form
The **distribution metadata** refers to, more specifically, the concrete form
core metadata takes when included inside a distribution archive
(``PKG-INFO`` in a sdist and ``METADATA`` in a wheel) or installed project
(``METADATA``).
@ -274,18 +245,16 @@ for the purposes of this PEP (``Syn:``).
metadata format key.
**Distribution Package** *(Sub: Package, Distribution Archive)*
A versioned archive file that contains Python packages, modules, and other
resource files that are used to distribute a Release.
*(PyPUG Glossary)*
(`See PyPUG <#pypugdistributionpackage_>`__)
In this PEP, **package** is used to refer to the abstract concept of a
distributable form of a Python project, while **distribution** more
specifically references the physical **distribution archive**.
**License Classifier**
A `PyPI Trove classifier <#classifiers_>`_ (as originally defined in :pep:`301`)
which begins with ``License ::``, currently used to indicate a project's
license status by including it as a ``Classifier`` in the core metadata.
A `PyPI Trove classifier <#classifiers_>`_ (as originally defined in
:pep:`301`) which begins with ``License ::``, currently used to indicate
a project's license status by including it as a ``Classifier``
in the core metadata.
**License Expression** *(Syn: SPDX Expression)*
A string with valid `SPDX license expression syntax <#spdxpression_>`_
@ -300,13 +269,7 @@ for the purposes of this PEP (``Syn:``).
and ``LicenseRef-Proprietary`` strings. Examples: ``MIT``, ``GPL-3.0-only``
**Project** *(Sub: Project Source Tree, Installed Project)*
A library, framework, script, plugin, application, collection of data
or other resources, or some combination thereof that is intended to be
packaged into a Distribution. Generally contains a ``pyproject.toml``,
``setup.py``, or ``setup.cfg`` file at the root of the project source
directory.
*(PyPUG Glossary)*
(`See PyPUG <#pypugproject_>`__)
Here, a **project source tree** refers to the on-disk format of
a project used for development, while an **installed project** is the form a
project takes once installed from a distribution, as
@ -334,10 +297,6 @@ for the purposes of this PEP (``Syn:``).
containing the core metadata (i.e., the ``.dist-info/license_files``
directory) for built distributions and installed projects.
**Source Distribution** *(Short: sdist)*
Here, specifically refers to a source distribution (**sdist**) as
`specified by PyPA <#sdistspec_>`_.
**Tool** *(Sub: Packaging Tool, Build Tool, Install Tool, Publishing Tool)*
A program, script or service executed by the user or automatically that
seeks to conform to the specification defined in this PEP.
@ -358,11 +317,11 @@ for the purposes of this PEP (``Syn:``).
A **publishing tool** is a packaging tool used to upload distribution
archives to a package index, such as Twine for PyPI.
**Wheel Format** *(Short: wheel, Rel: Wheel project)*
Here, **wheel**, the standard built distribution format introduced in :pep:`427`
and `specified by PyPA <#wheelspec_>`_, will be referred to in lowercase,
while the `Wheel project <#wheelproject_>`_, its reference implementation,
will be referred to as **Wheel** in Title Case.
**Wheel** *(Short: wheel, Rel: wheel format, Wheel project)*
Here, **wheel**, the standard built distribution format introduced in
:pep:`427` and `specified by PyPA <#wheelspec_>`_, will be referred to in
lowercase, while the `Wheel project <#wheelproject_>`_, its reference
implementation, will be referred to as such with **Wheel** in Title Case.
Specification
@ -469,13 +428,23 @@ version.
Add ``License-File`` field
''''''''''''''''''''''''''
The ``License-File`` optional field is specified to contain the string
representation of the path to a license-related file, relative to the
root license directory. It is a multi-use field that may appear zero or
Each instance of the ``License-File`` optional field is specified to contain
the string representation of the path in the project source tree, relative to
the project root directory, of a license-related file.
It is a multi-use field that may appear zero or
more times, each instance listing the path to one such file. Files specified
under this field could include license text, author/attribution information,
or other legal notices that need to be distributed with the package.
As `specified by this PEP <License files in project formats_>`__, its value
is also that file's path relative to the root license directory in both
installed projects and the standardized distribution package types.
In other legacy, non-standard or new distribution package formats and
mechanisms of accessing and storing core metadata, the value MAY correspond
to the license file path relative to a format-defined root license directory.
Alternatively, it MAY be treated as a unique abstract key to access the
license file contents by another means, as specified by the format.
If a ``License-File`` is listed in a source or built distribution's core
metadata, that file MUST be included in the distribution at the specified path
relative to the root license directory, and MUST be installed with the
@ -487,7 +456,7 @@ projects. Therefore, inside the root license directory, packaging tools
MUST reproduce the directory structure under which the
source license files are located relative to the project root.
Path separators MUST be the forward slash character (``/``),
Path delimiters MUST be the forward slash character (``/``),
and parent directory indicators (``..``) MUST NOT be used.
License file content MUST be UTF-8 encoded text.
@ -593,7 +562,7 @@ Add ``license-files`` key
'''''''''''''''''''''''''
A new ``license-files`` key is added to the ``project`` table for specifying
paths in the project source relative to ``pyproject.toml`` to file(s)
paths in the project source tree relative to ``pyproject.toml`` to file(s)
containing licenses and other legal notices to be distributed with the package.
It corresponds to the ``License-File`` fields in the core metadata.
@ -609,7 +578,7 @@ Python standard library.
as the value for the ``license-files`` key has been
`left out for now <Also allow a flat array value_>`_.
Path separators, if used, MUST be the forward slash character (``/``),
Path delimiters MUST be the forward slash character (``/``),
and parent directory indicators (``..``) MUST NOT be used.
Tools MUST assume that license file content is valid UTF-8 encoded text,
and SHOULD validate this and raise an error if it is not.
@ -869,143 +838,6 @@ MUST NOT automatically infer a license expression, and SHOULD suggest that the
package author construct one which expresses their intent.
User Scenarios
==============
The following covers the range of common use cases from a user perspective,
providing straightforward guidance for each. Do note that the following
should **not** be considered legal advice, and readers should consult a
licensed attorney if they are unsure about the specifics for their situation.
I have a private package that won't be distributed
--------------------------------------------------
If your package isn't shared publicly, i.e. outside your company,
organization or household, it *usually* isn't strictly necessary to include
a formal license, so you wouldn't necessarily have to do anything extra here.
However, it is still a good idea to include ``LicenseRef-Proprietary``
as a license expression in your package configuration, and/or a
copyright statement and any legal notices in a ``LICENSE.txt`` file
in the root of your project directory, which will be automatically
included by packaging tools.
I just want to share my own work without legal restrictions
-----------------------------------------------------------
While you aren't required to include a license, if you don't, no one has
`any permission to download, use or improve your work <#dontchoosealicense_>`_,
so that's probably the *opposite* of what you actually want.
The `MIT license <#mitlicense_>`_ is a great choice instead, as it's simple,
widely used and allows anyone to do whatever they want with your work
(other than sue you, which you probably also don't want).
To apply it, just paste `the text <#chooseamitlicense_>`_ 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
``[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!
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
``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``
and copyable license text on sites like
`ChooseALicense <#choosealicenselist_>`_ or `SPDX <#spdxlist_>`_.
Many popular code hosts, project templates and packaging tools can add the
license file for you, and may support the expression as well in the future.
I maintain an existing package that's already licensed
------------------------------------------------------
If you already have license files and metadata in your project, you
should only need to make a couple of tweaks to take advantage of the new
functionality.
In your project config file, enter your license expression under
``license-expression`` (:pep:`621` ``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
``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 <#spdxlist_>`_ for the identifier
that matches the license used in your project.
If your license files begin with ``LICENSE``, ``COPYING``, ``NOTICE`` or
``AUTHORS``, or you've already configured your packaging tool to add them
(e.g. ``license_files`` in ``setup.cfg``), you should already be good to go.
If not, make sure to list them under ``license-files.paths``
or ``license-files.globs`` under ``[project]`` in ``pyproject.toml``
(if your tool supports it), or else in your tool's configuration file
(e.g. ``license_files`` in ``setup.cfg`` for Setuptools).
See the `basic example`_ for a simple but complete real-world demo of how
this works in practice, including some additional technical details.
Packaging tools may support automatically converting legacy licensing
metadata; check your tool's documentation for more information.
My package includes other code under different licenses
-------------------------------------------------------
If your project includes code from others covered by different licenses,
such as vendored dependencies or files copied from other open source
software, you can construct a license expression (or have a tool
help you do so) to describe the licenses involved and the relationship
between them.
In short, ``License-1 AND License-2`` mean that *both* licenses apply
to your project, or parts of it (for example, you included a file
under another license), and ``License-1 OR License-2`` means that
*either* of the licenses can be used, at the user's option (for example,
you want to allow users a choice of multiple licenses). You can use
parenthesis (``()``) for grouping to form expressions that cover even the most
complex situations.
In your project config file, enter your license expression under
``license-expression`` (:pep:`621` ``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
``License ::`` classifiers.
Also, make sure you add the full license text of all the licenses as files
somewhere in your project repository. If all of them are in the root directory
and begin with ``LICENSE``, ``COPYING``, ``NOTICE`` or ``AUTHORS``,
they will be included automatically. Otherwise, you'll need to list the
relative path or glob patterns to each of them under ``license-files.paths``
or ``license-files.globs`` under ``[project]`` in ``pyproject.toml``
(if your tool supports it), or else in your tool's configuration file
(e.g. ``license_files`` in ``setup.cfg`` for Setuptools).
As an example, if your project was licensed MIT but incorporated
a vendored dependency (say, ``packaging``) that was licensed under
either Apache 2.0 or the 2-clause BSD, your license expression would
be ``MIT AND (Apache-2.0 OR BSD-2-Clause)``. You might have a
``LICENSE.txt`` in your repo root, and a ``LICENSE-APACHE.txt`` and
``LICENSE-BSD.txt`` in the ``_vendor`` subdirectory, so to include
all of them, you'd specify ``["LICENSE.txt", "_vendor/packaging/LICENSE*"]``
as glob patterns, or
``["LICENSE.txt", "_vendor/LICENSE-APACHE.txt", "_vendor/LICENSE-BSD.txt"]``
as literal file paths.
See a fully worked out `advanced example`_ for a comprehensive end-to-end
application of this to a real-world complex project, with copious technical
details, and consult a `tutorial <#spdxtutorial_>`_ for more help and examples
using SPDX identifiers and expressions.
Backwards Compatibility
=======================
@ -2100,8 +1932,8 @@ compatibility, while the same is not so if they are allowed now and later
determined to be unnecessary or too problematic in practice.
Appendix 1. License Expression Examples
=======================================
Appendix: License Expression Examples
=====================================
Basic example
-------------
@ -2292,8 +2124,146 @@ Some additional examples of valid ``License-Expression`` values::
License-Expression: LicenseRef-Proprietary
Appendix 2. License Documentation in Python
===========================================
Appendix: User Scenarios
========================
The following covers the range of common use cases from a user perspective,
providing straightforward guidance for each. Do note that the following
should **not** be considered legal advice, and readers should consult a
licensed legal practitioner in their jurisdiction if they are unsure about
the specifics for their situation.
I have a private package that won't be distributed
--------------------------------------------------
If your package isn't shared publicly, i.e. outside your company,
organization or household, it *usually* isn't strictly necessary to include
a formal license, so you wouldn't necessarily have to do anything extra here.
However, it is still a good idea to include ``LicenseRef-Proprietary``
as a license expression in your package configuration, and/or a
copyright statement and any legal notices in a ``LICENSE.txt`` file
in the root of your project directory, which will be automatically
included by packaging tools.
I just want to share my own work without legal restrictions
-----------------------------------------------------------
While you aren't required to include a license, if you don't, no one has
`any permission to download, use or improve your work <#dontchoosealicense_>`_,
so that's probably the *opposite* of what you actually want.
The `MIT license <#mitlicense_>`_ is a great choice instead, as it's simple,
widely used and allows anyone to do whatever they want with your work
(other than sue you, which you probably also don't want).
To apply it, just paste `the text <#chooseamitlicense_>`_ 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
``[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!
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
``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``
and copyable license text on sites like
`ChooseALicense <#choosealicenselist_>`_ or `SPDX <#spdxlist_>`_.
Many popular code hosts, project templates and packaging tools can add the
license file for you, and may support the expression as well in the future.
I maintain an existing package that's already licensed
------------------------------------------------------
If you already have license files and metadata in your project, you
should only need to make a couple of tweaks to take advantage of the new
functionality.
In your project config file, enter your license expression under
``license-expression`` (:pep:`621` ``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
``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 <#spdxlist_>`_ for the identifier
that matches the license used in your project.
If your license files begin with ``LICENSE``, ``COPYING``, ``NOTICE`` or
``AUTHORS``, or you've already configured your packaging tool to add them
(e.g. ``license_files`` in ``setup.cfg``), you should already be good to go.
If not, make sure to list them under ``license-files.paths``
or ``license-files.globs`` under ``[project]`` in ``pyproject.toml``
(if your tool supports it), or else in your tool's configuration file
(e.g. ``license_files`` in ``setup.cfg`` for Setuptools).
See the `basic example`_ for a simple but complete real-world demo of how
this works in practice, including some additional technical details.
Packaging tools may support automatically converting legacy licensing
metadata; check your tool's documentation for more information.
My package includes other code under different licenses
-------------------------------------------------------
If your project includes code from others covered by different licenses,
such as vendored dependencies or files copied from other open source
software, you can construct a license expression (or have a tool
help you do so) to describe the licenses involved and the relationship
between them.
In short, ``License-1 AND License-2`` mean that *both* licenses apply
to your project, or parts of it (for example, you included a file
under another license), and ``License-1 OR License-2`` means that
*either* of the licenses can be used, at the user's option (for example,
you want to allow users a choice of multiple licenses). You can use
parenthesis (``()``) for grouping to form expressions that cover even the most
complex situations.
In your project config file, enter your license expression under
``license-expression`` (:pep:`621` ``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
``License ::`` classifiers.
Also, make sure you add the full license text of all the licenses as files
somewhere in your project repository. If all of them are in the root directory
and begin with ``LICENSE``, ``COPYING``, ``NOTICE`` or ``AUTHORS``,
they will be included automatically. Otherwise, you'll need to list the
relative path or glob patterns to each of them under ``license-files.paths``
or ``license-files.globs`` under ``[project]`` in ``pyproject.toml``
(if your tool supports it), or else in your tool's configuration file
(e.g. ``license_files`` in ``setup.cfg`` for Setuptools).
As an example, if your project was licensed MIT but incorporated
a vendored dependency (say, ``packaging``) that was licensed under
either Apache 2.0 or the 2-clause BSD, your license expression would
be ``MIT AND (Apache-2.0 OR BSD-2-Clause)``. You might have a
``LICENSE.txt`` in your repo root, and a ``LICENSE-APACHE.txt`` and
``LICENSE-BSD.txt`` in the ``_vendor`` subdirectory, so to include
all of them, you'd specify ``["LICENSE.txt", "_vendor/packaging/LICENSE*"]``
as glob patterns, or
``["LICENSE.txt", "_vendor/LICENSE-APACHE.txt", "_vendor/LICENSE-BSD.txt"]``
as literal file paths.
See a fully worked out `advanced example`_ for a comprehensive end-to-end
application of this to a real-world complex project, with copious technical
details, and consult a `tutorial <#spdxtutorial_>`_ for more help and examples
using SPDX identifiers and expressions.
Appendix: License Documentation in Python
=========================================
There are multiple ways used or recommended to document Python project
licenses today. The most common are listed below.
@ -2418,8 +2388,8 @@ Other Python packaging tools
``pyproject.toml`` with SPDX license identifiers.
Appendix 3. License Documentation in Other Projects
===================================================
Appendix: License Documentation in Other Projects
=================================================
Here is a survey of how things are done elsewhere.
@ -2668,7 +2638,9 @@ References
.. _#poetry: https://python-poetry.org/docs/pyproject/#license
.. _#pycode: https://github.com/search?l=Python&q=%22__license__%22&type=Code
.. _#pypi: https://pypi.org/
.. _#pypugdistributionpackage: https://packaging.python.org/en/latest/glossary/#term-Distribution-Package
.. _#pypugglossary: https://packaging.python.org/glossary/
.. _#pypugproject: https://packaging.python.org/en/latest/glossary/#term-Project
.. _#pytorch: https://pypi.org/project/torch/
.. _#reuse: https://reuse.software/
.. _#reusediscussion: https://github.com/pombredanne/spdx-pypi-pep/issues/7