Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

附录:Python 及其他项目中的许可证文档

摘要

有多种方法被使用或推荐用于文档化许可证。本文档包含了对 Python 及其他语言中许可证文档进行全面调查的结果。

调查的关键要点(指导了 PEP 639 的建议)如下:

  • 大多数包格式使用单个 License 字段。
  • 许多现代包系统使用某种形式的 许可证表达式 来可选地组合多个 许可证标识符。SPDX 和类 SPDX 语法是最流行的用法。
  • SPDX 许可证标识符正在成为引用通用许可证的事实标准,无论是否使用完整的许可证表达式语法。
  • 几个包格式支持文档化许可证表达式和包含许可证文本的相应文件的路径。大多数自由和开源软件许可证要求包作者在其 分发包 中包含其完整文本。

Python 中的许可证文档

核心元数据

有两个重叠的核心元数据字段用于文档化许可证:以 License :: 为前缀的许可证 Classifier 字符串 和作为自由文本的 License 字段

核心元数据 License 字段的文档目前是

License
=======

.. versionadded:: 1.0

Text indicating the license covering the distribution where the license
is not a selection from the "License" Trove classifiers. See
:ref:`"Classifier" <metadata-classifier>` below.
This field may also be used to specify a
particular version of a license which is named via the ``Classifier``
field, or to indicate a variation or exception to such a license.

Examples::

    License: This software may only be obtained by sending the
            author a postcard, and then the user promises not
            to redistribute it.

    License: GPL version 3, excluding DRM provisions

尽管有两个字段,但有时难以传达比简单许可更复杂的信息。例如,一些分类器缺乏精确性(例如,没有版本的 GPL),并且当列出多个许可证分类器时,不清楚是必须应用所有许可证,还是用户可以在它们之间进行选择。此外,可用的许可证分类器列表相当有限且过时。

Setuptools 和 Wheel

除了许可证代码或限定符之外,许可证文本文件会通过隐式或显式的方式进行文档化并包含在构建的包中,这是另一个可能的混淆来源。

  • SetuptoolsWheel 项目中,如果许可证文件名称与一组常见的许可证文件名称模式(LICEN[CS]E*COPYING*NOTICE*AUTHORS*)匹配,则会自动添加到分发包中(在源分发/sdist 的源位置,以及在构建的 wheel 的 .dist-info 目录中)。或者,包作者可以通过项目 setup.cfg[metadata] 部分的 license_files 键,或作为 setuptools.setup() 函数的参数,指定要包含在构建的 wheel 中的许可证文件路径列表。目前,遵循 Wheel 项目的模式,Setuptools 将收集到的许可证文件展平到元数据目录中,覆盖同名文件,并将许可证文件直接转储到顶层 .dist-info 目录中,但 有解决这两个问题的愿望,这取决于 PEP 639 是否被接受。
  • 这两个工具还支持一个较旧的、单一的 license_file 参数,该参数允许仅指定一个许可证文件添加到分发包中,该参数已弃用一段时间但仍有 一些使用
  • 在 PEP 639 的早期草案发布后,Setuptools 增加了对 此规范所述的分发元数据中 License-File 的支持。这使得其他工具在使用生成的元数据时能够明确地定位给定包的许可证文件。

PyPA 打包指南和示例项目

PyPA 的初学者打包教程和更全面的打包指南都指出,每个包都包含许可证文件很重要。它们以官方 PyPA 示例项目中的 LICENSE.txt 为例,该文件在 setup.cfglicense_files 键下被 明确列出,遵循 PEP 639 正式指定的现有实践。

初学者打包教程和示例项目仅使用分类器来声明包的许可证,并且不包含或提及 License 字段。完整的打包指南确实提到了这个字段,但指出作者应该使用许可证分类器,除非项目使用非标准许可证(指南不鼓励这种情况)。

Python 源代码文件

注意: 在源代码中文档化许可证不在 PEP 639 的范围内。

除了使用注释和/或 SPDX-License-Identifier 约定之外,许可证 有时 在 Python 代码文件中通过一个“dunder”模块级常量来文档化,通常命名为 __license__

这个约定,虽然可能有些过时,但被内置的 help() 函数和标准的 pydoc 模块所识别。dunder 变量将显示在模块的 help() DATA 部分。

其他项目中的许可证文档

Linux 发行版包

注意: 在大多数情况下,最常见许可证的文本包含在全局共享的文档目录中(例如 /usr/share/doc)。

  • Debian 使用 机器可读的版权文件 来文档化包许可证。它定义了自己的许可证表达式语法和常用许可证的标识符列表,这两者都与 SPDX 非常相似。
  • Fedora 包 规定了如何包含 许可证文本,并使用一个 许可证字段,该字段必须用来自广泛的 “良好许可证” 列表中的适当短许可证标识符填写。Fedora 使用 SPDX 许可证表达式语法。
  • OpenSUSE 包 使用 SPDX 许可证表达式,并带有 SPDX 许可证 ID 和 其他许可证标识符列表
  • Gentoo ebuild 使用 LICENSE 变量。此字段在 GLEP-0023 和 Gentoo 开发手册中进行了规定。Gentoo 还定义了一个允许的许可证列表和许可证表达式语法,这与 SPDX 有很大不同。
  • FreeBSD 包 Makefile 提供了 LICENSELICENSE_FILE 字段,并带有自定义许可证符号列表。对于非标准许可证,FreeBSD 建议使用 LICENSE=UNKNOWN,并添加 LICENSE_NAMELICENSE_TEXT 字段,以及复杂的 LICENSE_PERMS 来限定许可证权限,以及 LICENSE_GROUPS 来文档化许可证分组。LICENSE_COMB 允许文档化多个许可证以及它们如何组合在一起,形成自定义的许可证表达式语法。FreeBSD 还建议在源代码文件中使用 SPDX-License-Identifier
  • Arch Linux PKGBUILD 定义了其 自己的许可证标识符。如果许可证未定义,则可以使用值 'unknown'
  • OpenWRT ipk 包 使用 PKG_LICENSEPKG_LICENSE_FILES 变量,并推荐使用 SPDX 许可证标识符。
  • NixOS 在其许可证字段中使用了 SPDX 标识符 和一些额外的许可证 ID。
  • GNU Guix(基于 NixOS)有一个单一的 License 字段,使用自己的 许可证符号列表,并指定了如何使用一个许可证或 它们的列表
  • Alpine Linux 包 推荐在许可证字段中使用 SPDX 标识符。

语言和应用程序包

  • 在 Java 中,Maven POM 定义了一个 licenses XML 标签,其中包含一个许可证列表,每个许可证都有名称、URL、注释和“分发”类型。这不是强制性的,并且每个字段的内容都没有指定。
  • JavaScript NPM package.json 使用单个许可证字段,该字段可以是 SPDX 许可证表达式,或者如果没有指定则为 UNLICENSED ID。可以通过在单个 license 字段中使用 SEE LICENSE IN <filename> 来作为替代引用许可证文件。
  • Rubygems gemspec 指定单个或多个许可证字符串。列表中多个许可证之间的关系未指定。他们推荐使用 SPDX 许可证标识符。
  • CPAN Perl 模块 使用单个许可证字段,该字段是单个或多个字符串。列表中许可证之间的关系未指定。有一个自定义许可证标识符列表,加上这些通用标识符:open_sourcerestrictedunrestrictedunknown
  • Rust Cargolicense 字段中指定使用 SPDX 许可证表达式(v2.1)。它还支持使用斜杠分隔的 SPDX 许可证标识符的替代表达式语法,还有一个 license_file 字段。crates.io 包注册表 要求在上传包时设置 licenselicense_file 字段。
  • PHP composer.json 使用一个 license 字段,其值为 SPDX 许可证 ID 或 proprietarylicense 字段可以是单个字符串,其格式类似于带有 andor 关键字的 SPDX 许可证表达式;或者,如果存在(析取的)许可证选择,则是一个字符串列表。
  • NuGet 包 以前只使用简单的许可证 URL,但现在指定使用 SPDX 许可证表达式和/或包内的许可证文件路径。NuGet.org 存储库声明他们只接受“开源促进会或自由软件基金会批准”的许可证表达式。
  • Go 语言模块 go.mod 除了依赖关系之外,没有任何元数据提供。许可证信息留给代码作者和其他社区包管理器来文档化。
  • Dart/Flutter 规范 建议使用单个 LICENSE 文件,其中应包含所有许可证文本,每个文本之间用一条由 80 个连字符组成的行分隔。
  • JavaScript Bowerlicense 字段是单个字符串或字符串列表,使用 SPDX 许可证标识符,或许可证文件的路径/URL。
  • Cocoapods podspeclicense 字段是单个字符串,或一个带有 typefiletext 键的映射。除非提供了 LICENSE/LICENCE 文件,否则这是强制性的。
  • Haskell Cabal 从 2.2 版本开始接受 SPDX 许可证表达式。使用的 SPDX 许可证列表版本是 Cabal 版本的函数。该规范还提供了旧版(SPDX 之前)和 SPDX 许可证标识符之间的映射。Cabal 还指定了一个 license-file(s) 字段,列出了要与包一起安装的许可证文件。
  • Erlang/Elixir mix/hex 包 指定了一个 licenses 字段,这是一个必需的许可证字符串列表,并推荐使用 SPDX 许可证标识符。
  • D 语言 dub 包 定义了自己的许可证标识符列表和许可证表达式语法,类似于 SPDX 标准。
  • R 包 DESCRIPTION 定义了自己的复杂的许可证表达式语法和许可证标识符列表。R 在其许可证表达式语法中以独特的方式支持许可证版本说明符(例如 LGPL (>= 2.0, < 3))。

其他生态系统

  • SPDX-License-Identifier 头部 是一个简单的约定,用于在文件内部文档化许可证。
  • 自由软件基金会 (FSF) 提倡使用 SPDX 许可证标识符以提高 GPL 和其他版本化的自由软件许可证的清晰度,请参阅 GPL
  • 欧洲自由软件基金会 (FSFE) 的 REUSE 项目 提倡使用 SPDX-License-Identifier
  • Linux 内核 使用 SPDX-License-Identifier 和 FSFE REUSE 约定的部分来文档化其许可证。
  • U-Boot 带头在代码中使用 SPDX-License-Identifier,现在遵循 Linux 的方法。
  • Apache 软件基金会项目使用 RDF DOAP,其中一个许可证字段指向 SPDX 许可证标识符。
  • Eclipse 基金会 提倡使用 SPDX-license-Identifiers
  • ClearlyDefined 项目 提倡使用 SPDX 许可证标识符和表达式以提高许可证的清晰度。
  • Android 开源项目 使用 MODULE_LICENSE_XXX 空标签文件,其中 XXX 是一个许可证代码,例如 BSDAPACHEGPL 等。它还使用一个 NOTICE 文件,其中包含许可证和通知文本。