PEP 459 – Python 软件包的标准元数据扩展
- 作者:
- Alyssa Coghlan <ncoghlan at gmail.com>
- BDFL 委托:
- Alyssa Coghlan <ncoghlan at gmail.com>
- 讨论至:
- Distutils-SIG 邮件列表
- 状态:
- 已撤回
- 类型:
- 标准跟踪
- 主题:
- 打包
- 要求:
- 426
- 创建日期:
- 2013年11月11日
- 发布历史:
- 2013年12月21日
PEP 撤回
此 PEP 依赖于 PEP 426,而 PEP 426 本身已被撤销。详情请参阅该 PEP 中的 PEP 撤销部分。
在此期间,元数据扩展将继续按以往方式处理,例如 entry_points.txt:作为安装到元数据目录中的附加文件,与主 METADATA 文件一起。
摘要
本 PEP 描述了 Python 元数据的几个标准扩展。
与所有元数据扩展一样,每个标准扩展格式都有独立的版本。更改任何格式都需要更新此 PEP,但不需要更新核心打包元数据。
标准扩展命名空间
Python Package Index 上的 python 项目指的是 CPython 参考解释器。此命名空间用作标准元数据扩展的命名空间。
当前定义的标准扩展是
python.detailspython.projectpython.integratorpython.exportspython.commandspython.constraints
所有标准扩展目前都为 1.0 版本,因此可以省略 extension_metadata 字段而不会丢失任何功能。
python.details 扩展
python.details 扩展允许提供更多关于软件分发的信息。
python.details 扩展包含四个自定义子字段
license:分发的版权许可证keywords:分发的包索引关键词classifiers:分发的包索引 Trove 分类器document_names:其他元数据文件的名称
所有这些字段都是可选的。自动化工具必须在分发未提供这些字段时正确运行,包括在请求依赖于其中某个字段的操作时干净利落地失败。
许可
用于此分发的许可证的简短摘要字符串。
请注意,提供此字段的分发应仍在 分类器 字段中指定任何适用的许可证 Trove 分类器。即使提供了适当的 Trove 分类器,许可证摘要也可以作为指定特定版本许可证、或指示许可证的任何变体或例外情况的良好方法。
此字段应少于 512 个字符,且必须少于 2048 个字符。
此字段不应包含任何换行符。
完整的许可证文本应包含在分发源代码存档的单独文件中。有关详细信息,请参阅 文档名称。
示例
"license": "GPL version 3, excluding DRM provisions"
关键词
用于帮助在大型目录中搜索该分发的附加关键词列表。
示例
"keywords": ["comfy", "chair", "cushions", "too silly", "monty python"]
分类器
字符串列表,每个字符串提供一个分类值。分类器在 PEP 301 [2] 中进行了描述。
示例
"classifiers": [
"Development Status :: 4 - Beta",
"Environment :: Console (Text Based)",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)"
]
文档名称
分发 dist-info 元数据目录中包含的支持文档的文件名。
以下支持的文档可以命名
description:包含分发长描述的文件license:包含分发许可证完整文本的文件changelog:描述分发更改的文件
支持的文档必须直接包含在 dist-info 目录中。文档名称中不允许使用目录分隔符。
文件名的扩展名指示了(如果存在)文件标记格式。这允许索引服务器和其他自动化工具正确渲染包含的文本文档,并提供渲染错误的反馈,而无需猜测预期的格式。
如果文件名没有扩展名,或者扩展名未被识别,则默认渲染格式必须是纯文本。
以下标记渲染器应与指定的扩展名一起使用
- 纯文本:
.txt,无扩展名,未知扩展名 - reStructured Text:
.rst - Markdown:
.md - AsciiDoc:
.adoc,.asc,.asciidoc - HTML:
.html,.htm
自动化工具可以渲染一个或多个指定的格式为纯文本,也可以渲染列表中未包含的其他标记格式。
自动化工具不应对支持文档内容的长度做出任何假设,除非是为了保护服务的完整性。
示例
"document_names": {
"description": "README.rst",
"license": "LICENSE.rst",
"changelog": "NEWS"
}
python.project 扩展
python.project 扩展允许提供更多关于分发创建和维护的信息。
python.project 扩展包含三个自定义子字段
contacts:分发的关键联系点contributors:分发的其他贡献者project_urls:与分发相关的 URL
联系信息
个人和组织的详细信息记录为具有以下子字段的映射
name:个人或团体的名称email:电子邮件地址(可以是邮件列表)url:URL(例如源代码托管服务上的个人资料页面)role:以下之一"author"、"maintainer"或"contributor"
子字段 name 是必需的,其他子字段是可选的。
如果没有指定具体角色,则默认为 contributor。
电子邮件地址必须是 local-part@domain 的形式,其中 local-part 最长可达 64 个字符,整个电子邮件地址不超过 254 个字符。格式的正式规范在 RFC 5322(第 3.2.3 和 3.4.1 节)和 RFC 5321 中,在信息性 RFC 3696 及其勘误中也提供了更易读的形式。
定义的贡献者角色如下
author:分发的原始创建者maintainer:分发的当前主要贡献者(如果不是原始创建者)contributor:参与分发创建的任何其他个人或组织
联系人和贡献者元数据是可选的。自动化工具必须在分发未提供这些信息时正确运行,包括在请求依赖于其中某个字段的操作时干净利落地失败。
联系人
关于获取项目更多信息的推荐联系点的贡献者条目列表。
下面的示例适用于一个项目,该项目正在从原始作者向新的主要维护者移交,同时作为一个更大的开发团队的一部分运行。
示例
"contacts": [
{
"name": "Python Packaging Authority/Distutils-SIG",
"email": "distutils-sig@python.org",
"url": "https://bitbucket.org/pypa/"
},
{
"name": "Samantha C.",
"role": "maintainer",
"email": "dontblameme@example.org"
},
{
"name": "Charlotte C.",
"role": "author",
"email": "iambecomingasketchcomedian@example.com"
}
]
贡献者
未在当前项目联系点中列出的其他贡献者的贡献者条目列表。列表元素的子字段与主联系人字段相同。
示例
"contributors": [
{"name": "John C."},
{"name": "Erik I."},
{"name": "Terry G."},
{"name": "Mike P."},
{"name": "Graeme C."},
{"name": "Terry J."}
]
项目 URL
任意文本标签到与项目相关的其他 URL 的映射。
虽然项目可以自由选择自己的标签和特定 URL,但建议使用以下示例中的标签来提供主页、源代码控制、问题跟踪器和文档链接。
自动化工具必须将 URL 标签视为不区分大小写,但它们不要求是有效的 Python 标识符。任何合法的 JSON 字符串都可以用作 URL 标签。
示例
"project_urls": {
"Documentation": "https://distlib.readthedocs.org",
"Home": "https://bitbucket.org/pypa/distlib",
"Repository": "https://bitbucket.org/pypa/distlib/src",
"Tracker": "https://bitbucket.org/pypa/distlib/issues"
}
python.integrator 扩展
结构上,此扩展与 python.project 扩展基本相同(唯一的区别是扩展名)。
然而,在 project 元数据指向上游软件创建者时,integrator 元数据则指出了修改后版本的下游分发者。
如果软件被 unmodified 分发,那么通常不会使用此扩展。但是,如果软件已打补丁(例如,从后续版本向后移植兼容性修复,或解决平台兼容性问题),则应使用此扩展,并在分发的版本标识符中添加本地版本标签。
如果链中有多个分发者,每个分发者都用自己的元数据覆盖此扩展。
python.exports 扩展
大多数 Python 分发通过 Python 模块命名空间暴露包和模块供导入。分发在安装时也可以暴露其他接口。
python.exports 扩展包含三个自定义子字段
modules:分发导出的模块namespaces:分发贡献的命名空间包exports:分发导出的其他 Python 接口
导出说明符
导出说明符是一个字符串,由一个完全限定的名称以及一个可选的方括号内的附加名称组成。这给出了四种可能的导出说明符形式
module
module:name
module[requires_extra]
module:name[requires_extra]
注意
jsonschema 文件目前使用 Python 2 ASCII 标识符规则限制限定名称。考虑到 Python 3 中更宽松的标识符规则,这可能需要重新考虑。
子字段的含义如下
module:提供导出的模块name:如果适用,则为模块内导出项的限定名称requires_extra:指示导出项仅当附加依赖项(命名在给定的 extra 中)在已安装的环境中可用时才能正确工作
注意
我尝试将其用作带有子字段的映射,但这使得下面的示例难以阅读。虽然此 PEP 主要用于工具使用,但可读性在某种程度上仍然很重要,用于调试目的,并且因为我期望格式的片段能在其他地方重用。
模块
分发提供供导入的模块和包的完全限定名称列表。
注意
jsonschema 文件目前使用 Python 2 ASCII 标识符规则限制限定名称。考虑到 Python 3 中更宽松的标识符规则,这可能需要重新考虑。
对于包含点的名称,点前面的部分必须出现在已安装的模块列表或命名空间包列表中。
为了避免名称冲突,建议分发提供一个与分发名称(或其小写形式)匹配的顶级模块或包。这要求分发名称也满足 Python 标识符的要求,而 Python 标识符的要求比分发名称更严格。此做法还将更容易找到模块的权威来源。
索引服务器应允许多个分发发布相同的模块,但可以通知分发作者潜在的冲突。
安装工具在被要求安装一个提供与其他已安装分发相同的模块的分发时,应报告错误。
请注意,尝试导入某些声明的模块可能会导致异常,如果未安装相应的 extra 依赖项。
示例
"modules": ["chair", "chair.cushions", "python_sketches.nobody_expects"]
注意
将其变为导出说明符列表可以允许分发声明某个模块需要特定 extra 才能正确运行。另一方面,可以认为这开始变得值得将它们拆分成一个单独的分发,而不是使用 extra。
命名空间
分发贡献的命名空间包的完全限定名称列表。
注意
jsonschema 文件目前使用 Python 2 ASCII 标识符规则限制限定名称。考虑到 Python 3 中更宽松的标识符规则,这可能需要重新考虑。
在 Python 3.3 之前的 Python 版本(提供原生命名空间包支持)上,安装工具应在安装过程中发出合适的 __init__.py 文件来正确初始化命名空间,而不是使用分发提供的文件。
如果分发声明的命名空间包与已安装模块的名称冲突,或反之,安装工具应发出警告,并且可以发出错误。
示例
"namespaces": ["python_sketches"]
导出
exports 字段是一个映射,以带前缀的名称作为键。每个键标识一个导出组,其中包含分发发布的零个或多个导出项。导出组包含一个或多个导出项。
导出组名称由分发定义,然后分发将以某种方式利用发布的导出信息。主要用例是支持插件模型的分发:定义导出组允许其他分发指示它们提供的插件、如何导入和访问它们,以及(如果有)为插件正常工作所需的附加依赖项。
为了减少名称冲突的可能性,导出组名称应使用对应于分发中定义导出组含义的模块名称的 prefix。此做法还将使查找导出组的权威文档更加容易。
每个单独的导出组是一个任意的非空字符串键到导出说明符的映射。导出组内导出名称的含义由定义导出组的分发决定。创建导出名称格式的适当定义可以使导入分发能够确定导出是否相关,而无需导入所有导出模块。
示例
"exports": {
"nose.plugins.0.10": {
"chairtest": "chair:NosePlugin"
}
}
python.commands 扩展
python.commands 扩展包含三个自定义子字段
wrap_console:安装程序要生成的控制台包装脚本wrap_gui:安装程序要生成的 GUI 包装脚本prebuilt:由分发构建过程创建并直接安装到配置的脚本目录中的脚本
wrap_console 和 wrap_gui 都是脚本名称到导出说明符的映射。脚本名称必须遵循与分发名称相同的命名规则。
包装脚本的导出说明符必须引用一个带有 __main__ 子模块的包(如果导出说明符中未提供 name 子字段),或者引用命名模块内的可调用对象。
安装工具应在安装过程中生成适当的包装脚本。
注意
仍然需要更多关于“适当的包装脚本”的细节。目前,请参考 setuptools 和 zc.buildout 生成的包装脚本。
prebuilt 是脚本路径的列表,相对于 wheel 文件中的脚本目录或安装后的路径。它们仅用于提供信息 - 安装它们通过构建分发时创建文件的正常流程来处理。
构建工具应将此扩展标记为需要由安装程序处理。
索引服务器应允许多个分发发布相同的命令,但可以通知分发作者潜在的冲突。
安装工具在被要求安装一个提供与其他已安装分发相同的命令的分发时,应报告错误。
示例
"python.commands": {
"installer_must_handle": true,
"wrap_console": [{"chair": "chair:run_cli"}],
"wrap_gui": [{"chair-gui": "chair:run_gui"}],
"prebuilt": ["reduniforms"]
}
python.constraints 扩展
python.constraints 扩展包含两个自定义子字段
environments:支持的安装环境extension_metadata:其他已安装组件发布的扩展元数据的必需精确匹配
构建工具应将此扩展标记为需要由安装程序处理。
索引服务器应允许上传具有在该索引上无法满足的约束的分发,但可以通知分发作者任何此类潜在的兼容性问题。
如果分发指定了约束并且目标安装环境未能满足它们,安装工具应报告错误,至少应发出警告,并可以允许用户强制安装继续进行。
示例
"python.constraints": {
"installer_must_handle": true,
"environments": ["python_version >= 2.6"],
"extension_metadata": {
"fortranlib": {
"fortranlib.compatibility": {
"fortran_abi": "openblas-g77"
}
}
}
}
支持的环境
environments 子字段是指定分发明确支持的环境的字符串列表。如果环境至少匹配一个给定的环境标记,则该环境被认为是支持的。
如果元数据中未提供此字段,则假定该分发支持 Python 支持的任何平台。
单个条目是环境标记,如 PEP 426 中所述。
此字段的两个主要用途是声明支持的 Python 版本和底层操作系统。
指示支持的 Python 版本的示例
# Supports Python 2.6+
"environments": ["python_version >= '2.6'"]
# Supports Python 2.6+ (for 2.x) or 3.3+ (for 3.x)
"environments": ["python_version >= '3.3'",
"'3.0' > python_version >= '2.6'"]
指示支持的操作系统版本的示例
# Windows only
"environments": ["sys_platform == 'win32'"]
# Anything except Windows
"environments": ["sys_platform != 'win32'"]
# Linux or BSD only
"environments": ["'linux' in sys_platform",
"'bsd' in sys_platform"]
支持的 Python 版本因平台而异的示例
# The standard library's os module has long supported atomic renaming
# on POSIX systems, but only gained atomic renaming on Windows in Python
# 3.3. A distribution that needs atomic renaming support for reliable
# operation might declare the following supported environments.
"environment": ["python_version >= '2.6' and sys_platform != 'win32'",
"python_version >= '3.3' and sys_platform == 'win32'"]
扩展元数据约束
extension_metadata 子字段是一个从分发名称到扩展元数据片段的映射,这些片段应与目标安装环境中命名分发的元数据精确匹配。
每个子映射随后由元数据扩展名称到特定字段的精确预期值组成的映射构成。
例如,一个名为 fortranlib 的分发可能根据其构建方式发布不同的 FORTRAN ABI,任何安装到同一运行时环境的相关项目都应使用匹配的构建选项。这可以通过让基础分发发布一个自定义扩展来指示用于创建二进制扩展的构建选项来处理。
"extensions": {
"fortranlib.compatibility": {
"fortran_abi": "openblas-g77"
}
}
包含需要与基础分发兼容的二进制扩展的其他分发将在其自身的元数据中定义适当的约束。
"python.constraints": {
"installer_must_handle": true,
"extension_metadata": {
"fortranlib": {
"fortranlib.compatibility": {
"fortran_abi": "openblas-g77"
}
}
}
}
此约束指定
fortranlib必须已安装(这也应表示为正常依赖项,以便安装程序确保其已满足)- 已安装的
fortranlib版本必须在其发布的元数据中包含自定义的fortranlib.compatibility扩展。 - 该扩展的
fortan_abi子字段必须具有精确值openblas-g77。
如果所有这些条件都满足(分发已安装,指定的扩展包含在元数据中,指定的子字段具有精确指定的值),则认为约束已满足。
注意
主要预期用途是允许具有附加 ABI 兼容性要求的 C 扩展以一种任何安装工具都可以强制执行的方式来声明它们,而无需理解细节。特别是,许多基于 NumPy 的科学库需要使用一致的 FORTRAN 库集进行构建,因此有了“fortranlib”的例子。
这就是为什么不支持模式匹配或布尔逻辑的原因:即使是这个扩展的“简单”版本也相对复杂,并且目前没有令人信服的理由使其比现在更复杂。
版权
本文档已置于公共领域。
来源:https://github.com/python/peps/blob/main/peps/pep-0459.rst