|
| 1 | +.. _licensing-examples-and-user-scenarios: |
| 2 | + |
| 3 | + |
| 4 | +===================================== |
| 5 | +Licensing examples and user scenarios |
| 6 | +===================================== |
| 7 | + |
| 8 | + |
| 9 | +:pep:`639` has specified the way to declare a project's license and paths to |
| 10 | +license files and other legally required information. |
| 11 | +This document aims to provide clear guidance how to migrate from the legacy |
| 12 | +to the standardized way of declaring licenses. |
| 13 | + |
| 14 | + |
| 15 | +Licensing Examples |
| 16 | +================== |
| 17 | + |
| 18 | +Examples |
| 19 | +-------- |
| 20 | + |
| 21 | +.. _licensing-example-basic: |
| 22 | + |
| 23 | +Basic example |
| 24 | +''''''''''''' |
| 25 | + |
| 26 | +The Setuptools project itself, as of `version 59.1.1 <setuptools5911_>`__, |
| 27 | +does not use the ``License`` field in its own project source metadata. |
| 28 | +Further, it no longer explicitly specifies ``license_file``/``license_files`` |
| 29 | +as it did previously, since Setuptools relies on its own automatic |
| 30 | +inclusion of license-related files matching common patterns, |
| 31 | +such as the ``LICENSE`` file it uses. |
| 32 | + |
| 33 | +It includes the following license-related metadata in its ``setup.cfg``: |
| 34 | + |
| 35 | +.. code-block:: ini |
| 36 | + |
| 37 | + [metadata] |
| 38 | + classifiers = |
| 39 | + License :: OSI Approved :: MIT License |
| 40 | + |
| 41 | +The simplest migration to PEP 639 would consist of using this instead: |
| 42 | + |
| 43 | +.. code-block:: ini |
| 44 | + |
| 45 | + [metadata] |
| 46 | + license_expression = MIT |
| 47 | + |
| 48 | +Or, in the ``[project]`` table of ``pyproject.toml``: |
| 49 | + |
| 50 | +.. code-block:: toml |
| 51 | + |
| 52 | + [project] |
| 53 | + license = "MIT" |
| 54 | + |
| 55 | +The output Core Metadata for the distribution packages would then be: |
| 56 | + |
| 57 | +.. code-block:: email |
| 58 | + |
| 59 | + License-Expression: MIT |
| 60 | + License-File: LICENSE |
| 61 | + |
| 62 | +The ``LICENSE`` file would be stored at ``/setuptools-${VERSION}/LICENSE`` |
| 63 | +in the sdist and ``/setuptools-${VERSION}.dist-info/licenses/LICENSE`` |
| 64 | +in the wheel, and unpacked from there into the site directory (e.g. |
| 65 | +``site-packages``) on installation; ``/`` is the root of the respective archive |
| 66 | +and ``${VERSION}`` the version of the Setuptools release in the Core Metadata. |
| 67 | + |
| 68 | + |
| 69 | +.. _licensing-example-advanced: |
| 70 | + |
| 71 | +Advanced example |
| 72 | +'''''''''''''''' |
| 73 | + |
| 74 | +Suppose Setuptools were to include the licenses of the third-party projects |
| 75 | +that are vendored in the ``setuptools/_vendor/`` and ``pkg_resources/_vendor`` |
| 76 | +directories; specifically: |
| 77 | + |
| 78 | +.. code-block:: text |
| 79 | + |
| 80 | + packaging==21.2 |
| 81 | + pyparsing==2.2.1 |
| 82 | + ordered-set==3.1.1 |
| 83 | + more_itertools==8.8.0 |
| 84 | + |
| 85 | +The license expressions for these projects are: |
| 86 | + |
| 87 | +.. code-block:: text |
| 88 | + |
| 89 | + packaging: Apache-2.0 OR BSD-2-Clause |
| 90 | + pyparsing: MIT |
| 91 | + ordered-set: MIT |
| 92 | + more_itertools: MIT |
| 93 | + |
| 94 | +A comprehensive license expression covering both Setuptools |
| 95 | +proper and its vendored dependencies would contain these metadata, |
| 96 | +combining all the license expressions into one. Such an expression might be: |
| 97 | + |
| 98 | +.. code-block:: text |
| 99 | + |
| 100 | + MIT AND (Apache-2.0 OR BSD-2-Clause) |
| 101 | + |
| 102 | +In addition, per the requirements of the licenses, the relevant license files |
| 103 | +must be included in the package. Suppose the ``LICENSE`` file contains the text |
| 104 | +of the MIT license and the copyrights used by Setuptools, ``pyparsing``, |
| 105 | +``more_itertools`` and ``ordered-set``; and the ``LICENSE*`` files in the |
| 106 | +``setuptools/_vendor/packaging/`` directory contain the Apache 2.0 and |
| 107 | +2-clause BSD license text, and the Packaging copyright statement and |
| 108 | +`license choice notice <packaginglicense_>`__. |
| 109 | + |
| 110 | +Specifically, we assume the license files are located at the following |
| 111 | +paths in the project source tree (relative to the project root and |
| 112 | +``pyproject.toml``): |
| 113 | + |
| 114 | +.. code-block:: ini |
| 115 | + |
| 116 | + LICENSE |
| 117 | + setuptools/_vendor/packaging/LICENSE |
| 118 | + setuptools/_vendor/packaging/LICENSE.APACHE |
| 119 | + setuptools/_vendor/packaging/LICENSE.BSD |
| 120 | + |
| 121 | +Putting it all together, our ``setup.cfg`` would be: |
| 122 | + |
| 123 | +.. code-block:: ini |
| 124 | + |
| 125 | + [metadata] |
| 126 | + license_expression = MIT AND (Apache-2.0 OR BSD-2-Clause) |
| 127 | + license_files = |
| 128 | + LICENSE |
| 129 | + setuptools/_vendor/packaging/LICENSE |
| 130 | + setuptools/_vendor/packaging/LICENSE.APACHE |
| 131 | + setuptools/_vendor/packaging/LICENSE.BSD |
| 132 | + |
| 133 | +In the ``[project]`` table of ``pyproject.toml``, license files |
| 134 | +can be specified via glob patterns: |
| 135 | + |
| 136 | +.. code-block:: toml |
| 137 | + |
| 138 | + [project] |
| 139 | + license = "MIT AND (Apache-2.0 OR BSD-2-Clause)" |
| 140 | + license-files = [ |
| 141 | + "LICENSE*", |
| 142 | + "setuptools/_vendor/LICENSE*", |
| 143 | + ] |
| 144 | + |
| 145 | +Or alternatively, they can be specified explicitly (paths will be interpreted |
| 146 | +as glob patterns): |
| 147 | + |
| 148 | +.. code-block:: toml |
| 149 | + |
| 150 | + [project] |
| 151 | + license = "MIT AND (Apache-2.0 OR BSD-2-Clause)" |
| 152 | + license-files = [ |
| 153 | + "LICENSE", |
| 154 | + "setuptools/_vendor/LICENSE", |
| 155 | + "setuptools/_vendor/LICENSE.APACHE", |
| 156 | + "setuptools/_vendor/LICENSE.BSD", |
| 157 | + ] |
| 158 | + |
| 159 | +With either approach, the output Core Metadata in the distribution |
| 160 | +would be: |
| 161 | + |
| 162 | +.. code-block:: email |
| 163 | + |
| 164 | + License-Expression: MIT AND (Apache-2.0 OR BSD-2-Clause) |
| 165 | + License-File: LICENSE |
| 166 | + License-File: setuptools/_vendor/packaging/LICENSE |
| 167 | + License-File: setuptools/_vendor/packaging/LICENSE.APACHE |
| 168 | + License-File: setuptools/_vendor/packaging/LICENSE.BSD |
| 169 | + |
| 170 | +In the resulting sdist, with ``/`` as the root of the archive and ``${VERSION}`` |
| 171 | +the version of the Setuptools release specified in the Core Metadata, |
| 172 | +the license files would be located at the paths: |
| 173 | + |
| 174 | +.. code-block:: shell |
| 175 | + |
| 176 | + /setuptools-${VERSION}/LICENSE |
| 177 | + /setuptools-${VERSION}/setuptools/_vendor/packaging/LICENSE |
| 178 | + /setuptools-${VERSION}/setuptools/_vendor/packaging/LICENSE.APACHE |
| 179 | + /setuptools-${VERSION}/setuptools/_vendor/packaging/LICENSE.BSD |
| 180 | + |
| 181 | +In the built wheel, with ``/`` being the root of the archive and |
| 182 | +``${VERSION}`` as the previous, the license files would be stored at: |
| 183 | + |
| 184 | +.. code-block:: shell |
| 185 | + |
| 186 | + /setuptools-${VERSION}.dist-info/licenses/LICENSE |
| 187 | + /setuptools-${VERSION}.dist-info/licenses/setuptools/_vendor/packaging/LICENSE |
| 188 | + /setuptools-${VERSION}.dist-info/licenses/setuptools/_vendor/packaging/LICENSE.APACHE |
| 189 | + /setuptools-${VERSION}.dist-info/licenses/setuptools/_vendor/packaging/LICENSE.BSD |
| 190 | + |
| 191 | +Finally, in the installed project, with ``site-packages`` being the site dir |
| 192 | +and ``${VERSION}`` as the previous, the license files would be installed to: |
| 193 | + |
| 194 | +.. code-block:: shell |
| 195 | + |
| 196 | + site-packages/setuptools-${VERSION}.dist-info/licenses/LICENSE |
| 197 | + site-packages/setuptools-${VERSION}.dist-info/licenses/setuptools/_vendor/packaging/LICENSE |
| 198 | + site-packages/setuptools-${VERSION}.dist-info/licenses/setuptools/_vendor/packaging/LICENSE.APACHE |
| 199 | + site-packages/setuptools-${VERSION}.dist-info/licenses/setuptools/_vendor/packaging/LICENSE.BSD |
| 200 | + |
| 201 | + |
| 202 | +Expression examples |
| 203 | +''''''''''''''''''' |
| 204 | + |
| 205 | +Some additional examples of valid ``License-Expression`` values: |
| 206 | + |
| 207 | +.. code-block:: email |
| 208 | + |
| 209 | + License-Expression: MIT |
| 210 | + License-Expression: BSD-3-Clause |
| 211 | + License-Expression: MIT AND (Apache-2.0 OR BSD-2-Clause) |
| 212 | + License-Expression: MIT OR GPL-2.0-or-later OR (FSFUL AND BSD-2-Clause) |
| 213 | + License-Expression: GPL-3.0-only WITH Classpath-Exception-2.0 OR BSD-3-Clause |
| 214 | + License-Expression: LicenseRef-Public-Domain OR CC0-1.0 OR Unlicense |
| 215 | + License-Expression: LicenseRef-Proprietary |
| 216 | + License-Expression: LicenseRef-Custom-License |
| 217 | + |
| 218 | + |
| 219 | +User Scenarios |
| 220 | +============== |
| 221 | + |
| 222 | +User Scenarios |
| 223 | +-------------- |
| 224 | + |
| 225 | +The following covers the range of common use cases from a user perspective, |
| 226 | +providing guidance for each. Do note that the following |
| 227 | +should **not** be considered legal advice, and readers should consult a |
| 228 | +licensed legal practitioner in their jurisdiction if they are unsure about |
| 229 | +the specifics for their situation. |
| 230 | + |
| 231 | + |
| 232 | +I have a private package that won't be distributed |
| 233 | +'''''''''''''''''''''''''''''''''''''''''''''''''' |
| 234 | + |
| 235 | +If your package isn't shared publicly, i.e. outside your company, |
| 236 | +organization or household, it *usually* isn't strictly necessary to include |
| 237 | +a formal license, so you wouldn't necessarily have to do anything extra here. |
| 238 | + |
| 239 | +However, it is still a good idea to include ``LicenseRef-Proprietary`` |
| 240 | +as a license expression in your package configuration, and/or a |
| 241 | +copyright statement and any legal notices in a ``LICENSE.txt`` file |
| 242 | +in the root of your project directory, which will be automatically |
| 243 | +included by packaging tools. |
| 244 | + |
| 245 | + |
| 246 | +I just want to share my own work without legal restrictions |
| 247 | +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' |
| 248 | + |
| 249 | +While you aren't required to include a license, if you don't, no one has |
| 250 | +`any permission to download, use or improve your work <dontchoosealicense_>`__, |
| 251 | +so that's probably the *opposite* of what you actually want. |
| 252 | +The `MIT license <mitlicense_>`__ is a great choice instead, as it's simple, |
| 253 | +widely used and allows anyone to do whatever they want with your work |
| 254 | +(other than sue you, which you probably also don't want). |
| 255 | + |
| 256 | +To apply it, just paste `the text <chooseamitlicense_>`__ into a file named |
| 257 | +``LICENSE.txt`` at the root of your repo, and add the year and your name to |
| 258 | +the copyright line. Then, just add ``license = "MIT"`` under |
| 259 | +``[project]`` in your ``pyproject.toml`` if your packaging tool supports it, |
| 260 | +or in its config file/section. You're done! |
| 261 | + |
| 262 | + |
| 263 | +I want to distribute my project under a specific license |
| 264 | +'''''''''''''''''''''''''''''''''''''''''''''''''''''''' |
| 265 | + |
| 266 | +To use a particular license, simply paste its text into a ``LICENSE.txt`` |
| 267 | +file at the root of your repo, if you don't have it in a file starting with |
| 268 | +``LICENSE`` or ``COPYING`` already, and add |
| 269 | +``license = "LICENSE-ID"`` under ``[project]`` in your |
| 270 | +``pyproject.toml`` if your packaging tool supports it, or else in its |
| 271 | +config file. You can find the ``LICENSE-ID`` |
| 272 | +and copyable license text on sites like |
| 273 | +`ChooseALicense <choosealicenselist_>`__ or `SPDX <spdxlist_>`__. |
| 274 | + |
| 275 | +Many popular code hosts, project templates and packaging tools can add the |
| 276 | +license file for you, and may support the expression as well in the future. |
| 277 | + |
| 278 | + |
| 279 | +I maintain an existing package that's already licensed |
| 280 | +'''''''''''''''''''''''''''''''''''''''''''''''''''''' |
| 281 | + |
| 282 | +If you already have license files and metadata in your project, you |
| 283 | +should only need to make a couple of tweaks to take advantage of the new |
| 284 | +functionality. |
| 285 | + |
| 286 | +In your project config file, enter your license expression under |
| 287 | +``license`` (``[project]`` table in ``pyproject.toml``), |
| 288 | +or the equivalent for your packaging tool, |
| 289 | +and make sure to remove any legacy ``license`` table subkeys or |
| 290 | +``License ::`` classifiers. Your existing ``license`` value may already |
| 291 | +be valid as one (e.g. ``MIT``, ``Apache-2.0 OR BSD-2-Clause``, etc); |
| 292 | +otherwise, check the `SPDX license list <spdxlist_>`__ for the identifier |
| 293 | +that matches the license used in your project. |
| 294 | + |
| 295 | +Make sure to list your license files under ``license-files`` |
| 296 | +under ``[project]`` in ``pyproject.toml`` |
| 297 | +or else in your tool's configuration file. |
| 298 | + |
| 299 | +See the :ref:`licensing-example-basic` for a simple but complete real-world demo |
| 300 | +of how this works in practiced. |
| 301 | +Packaging tools may support automatically converting legacy licensing |
| 302 | +metadata; check your tool's documentation for more information. |
| 303 | + |
| 304 | + |
| 305 | +My package includes other code under different licenses |
| 306 | +''''''''''''''''''''''''''''''''''''''''''''''''''''''' |
| 307 | + |
| 308 | +If your project includes code from others covered by different licenses, |
| 309 | +such as vendored dependencies or files copied from other open source |
| 310 | +software, you can construct a license expression |
| 311 | +to describe the licenses involved and the relationship |
| 312 | +between them. |
| 313 | + |
| 314 | +In short, ``License-1 AND License-2`` mean that *both* licenses apply |
| 315 | +to your project, or parts of it (for example, you included a file |
| 316 | +under another license), and ``License-1 OR License-2`` means that |
| 317 | +*either* of the licenses can be used, at the user's option (for example, |
| 318 | +you want to allow users a choice of multiple licenses). You can use |
| 319 | +parenthesis (``()``) for grouping to form expressions that cover even the most |
| 320 | +complex situations. |
| 321 | + |
| 322 | +In your project config file, enter your license expression under |
| 323 | +``license`` (``[project]`` table of ``pyproject.toml``), |
| 324 | +or the equivalent for your packaging tool, |
| 325 | +and make sure to remove any legacy ``license`` table subkeys |
| 326 | +or ``License ::`` classifiers. |
| 327 | + |
| 328 | +Also, make sure you add the full license text of all the licenses as files |
| 329 | +somewhere in your project repository. List the |
| 330 | +relative path or glob patterns to each of them under ``license-files`` |
| 331 | +under ``[project]`` in ``pyproject.toml`` |
| 332 | +(if your tool supports it), or else in your tool's configuration file. |
| 333 | + |
| 334 | +As an example, if your project was licensed MIT but incorporated |
| 335 | +a vendored dependency (say, ``packaging``) that was licensed under |
| 336 | +either Apache 2.0 or the 2-clause BSD, your license expression would |
| 337 | +be ``MIT AND (Apache-2.0 OR BSD-2-Clause)``. You might have a |
| 338 | +``LICENSE.txt`` in your repo root, and a ``LICENSE-APACHE.txt`` and |
| 339 | +``LICENSE-BSD.txt`` in the ``_vendor`` subdirectory, so to include |
| 340 | +all of them, you'd specify ``["LICENSE.txt", "_vendor/packaging/LICENSE*"]`` |
| 341 | +as glob patterns, or |
| 342 | +``["LICENSE.txt", "_vendor/LICENSE-APACHE.txt", "_vendor/LICENSE-BSD.txt"]`` |
| 343 | +as literal file paths. |
| 344 | + |
| 345 | +See a fully worked out :ref:`licensing-example-advanced` for an end-to-end |
| 346 | +application of this to a real-world complex project, with many technical |
| 347 | +details, and consult a `tutorial <spdxtutorial_>`__ for more help and examples |
| 348 | +using SPDX identifiers and expressions. |
| 349 | + |
| 350 | + |
| 351 | +.. _chooseamitlicense: https://choosealicense.com/licenses/mit/ |
| 352 | +.. _choosealicenselist: https://choosealicense.com/licenses/ |
| 353 | +.. _dontchoosealicense: https://choosealicense.com/no-permission/ |
| 354 | +.. _mitlicense: https://opensource.org/licenses/MIT |
| 355 | +.. _packaginglicense: https://github.com/pypa/packaging/blob/21.2/LICENSE |
| 356 | +.. _setuptools5911: https://github.com/pypa/setuptools/blob/v59.1.1/setup.cfg |
| 357 | +.. _spdxlist: https://spdx.org/licenses/ |
| 358 | +.. _spdxtutorial: https://github.com/david-a-wheeler/spdx-tutorial |
0 commit comments