PEP 625 – 源代码发行版的文件名
- 作者:
- Tzu-ping Chung <uranusjr at gmail.com>, Paul Moore <p.f.moore at gmail.com>
- PEP 委托人:
- Pradyun Gedam <pradyunsg at gmail.com>
- 讨论列表:
- Discourse 帖子
- 状态:
- 已接受
- 类型:
- 标准轨迹
- 主题:
- 打包
- 创建日期:
- 2020-07-08
- 更新历史:
- 2020-07-08
- 决议:
- Discourse 消息
摘要
本 PEP 描述了源代码发行版(也称为 sdist)的标准命名方案。sdist 与包含 Python 包源代码的任意归档文件不同,可用于将有关发行版的信息传达给打包工具。
此处指定的标准 sdist 是一个 gzip 压缩的 tar 文件,具有特殊格式的文件名和通常的 .tar.gz
后缀。本 PEP 未指定 tarball 的内容,因为这在其他规范中有所涵盖。
动机
sdist 是一种 Python 包发行版,包含 Python 包的“源代码”,并且需要构建步骤才能在安装时转换为 wheel。这种格式通常被认为是 PEP 427 wheel 的未构建对应物,并在打包生态系统的各个部分得到特殊处理。
sdist 的内容在 PEP 517 和 PEP 643 中指定,但目前 sdist 的文件名未完全指定,这意味着格式的使用者必须下载并处理 sdist 以确认其中包含的发行版的名称和版本。
安装程序目前依赖于启发式方法从文件名推断名称和/或版本,以帮助安装过程。例如,pip 从 PEP 503 索引中解析 sdist 的文件名,以获取发行版的项目名称和版本,以便进行依赖项解析。但由于缺乏规范,安装程序无法保证推断数据的正确性,并且必须在某个时候通过本地构建发行版元数据来验证它。
当用户不希望构建过程发生时,此构建步骤对于某些类型的操作来说很麻烦。pypa/pip#8387 描述了一个示例。命令 pip download --no-deps --no-binary=numpy numpy
预计只会下载 numpy 的 sdist,因为我们不需要检查依赖项,并且名称和版本都可以通过内省下载的文件名来获取。但是,pip 无法假设下载的存档遵循约定,并且必须构建并检查元数据。对于 PEP 518 项目,这意味着运行 PEP 517 中指定的 prepare_metadata_for_build_wheel
钩子,这会产生很大的开销。
基本原理
通过为 sdist 格式创建特殊的命名方案,本 PEP 使工具能够在只需要文件名中提供的元数据时免于耗时的元数据验证步骤。
本 PEP 还可以作为当前 sdist 实现使用的长期文件名约定的正式规范。文件名包含发行版名称和版本,以帮助工具识别发行版,而无需下载、解压缩文件并执行代价高昂的元数据生成以进行内省,如果它们需要的所有信息都包含在文件名中。
规范
sdist 的名称应为 {distribution}-{version}.tar.gz
。
distribution
是在 PEP 345 中定义的发行版名称,并按照 wheel 规范 中所述进行规范化,例如'pip'
、'flit_core'
。version
是在 PEP 440 中定义的发行版版本,例如20.2
,并根据该 PEP 中的规则进行规范化。
sdist 必须是 pax 格式的 gzip 压缩的 tar 存档,能够通过标准库 tarfile
模块使用打开标志 'r:gz'
进行提取。
生成 sdist 文件的代码必须为文件指定与本规范匹配的名称。PEP 517 中 build_sdist
钩子的规范已扩展到要求此命名约定。
处理 sdist 文件的代码可以简单地通过解析文件名来确定发行版名称和版本,并且不需要通过生成或读取 sdist 内容中的元数据来验证该信息。
符合标准的 sdist 文件可以通过 .tar.gz
后缀和文件名中的 单个 连字符来识别。请注意,某些旧版文件也可能符合这些条件,但这在实践中预计不会成为问题。有关更多详细信息,请参阅本文档的“向后兼容性”部分。
向后兼容性
新的文件名方案是当前 sdist 文件非正式命名约定的一个子集,因此符合此标准创建或发布文件的工具将可被仅了解先前命名约定的旧版工具读取。
使用 sdist 文件名的工具在技术上无法确定文件是使用新标准还是旧版格式。但是,对 PyPI 上的文件名进行审查确定,37% 的文件显然是旧版文件(因为它们包含多个或没有连字符),而在其余文件中,根据本 PEP 进行解析在除 0.004% 的情况下都能得到正确的结果。
目前,如果要完全正确,使用 sdist 的工具应将从文件名解析的名称和版本视为临时版本,并通过下载文件并生成实际元数据(或读取元数据,如果 sdist 符合 PEP 643)来验证它们。支持此规范的工具可以将文件名中的名称和版本视为最终版本。理论上,如果假设旧版文件名符合本 PEP,可能会导致错误,但在实践中,这种情况发生的可能性似乎微乎其微。
被拒绝的想法
依赖于 sdist 元数据的规范
自从本 PEP 首次编写以来,PEP 643 已被接受,定义了一种可靠的标准 sdist 元数据格式。这允许静态确定发行版元数据(尤其是名称和版本)。
然而,这被认为是不够的,因为在许多重要情况下(例如,从包索引中读取文件名),应用程序只能访问文件名,而读取元数据则需要进行可能代价高昂的下载。
使用专用的文件扩展名
本 PEP 的原始版本建议使用 {distribution}-{version}.sdist
的文件名。这具有明确性的优势,并且允许将来更改存储格式而无需进一步更改文件命名约定。
但是,新的扩展名存在重大的兼容性问题。索引服务器目前可能不允许未知扩展名,如果我们引入一个新的扩展名,则不清楚如何处理旧版索引尝试镜像托管新式 sdist 的索引的情况。是否可以仅部分镜像,省略项目更新版本的 sdist?此外,生成新格式的构建后端将与仅接受旧格式的索引服务器不兼容,并且由于用户在构建时通常无法请求后端的旧版本,因此这可能导致无法构建和上传 sdist。
扩展当前常见的 sdist 命名方案
在最初的讨论中提出了一个方案 {distribution}-{version}.sdist.tar.gz
。由于与当前可用的安装工具存在向后兼容性问题,因此放弃了该方案。例如,pip 20.1 会将 distribution-1.0.sdist.tar.gz
解析为项目 distribution
,版本为 1.0.sdist
。这会导致下载 sdist,但由于元数据不一致而无法安装。
此提案的主要优点是工具更容易识别新式命名。但是,这不是一个特别重要的优势,因为在旧规则和新规则下,所有文件名中只有一个连字符的 sdist 的解析方式都相同。
未解决的问题
sdist 的内容需要包含一个名为 {name}-{version}
的单个顶级目录。目前不需要对该名称的组件应用规范化规则。本 PEP 是否应该要求在此处应用与文件名相同的规范化规则?请注意,在实践中,工具可能会使用相同的代码创建这两个名称,因此即使没有明确要求,规范化也可能会自然发生。
版权
本文件置于公共领域或根据 CC0-1.0-Universal 许可证,以更宽松者为准。
来源:https://github.com/python/peps/blob/main/peps/pep-0625.rst
上次修改时间:2023-09-09 17:39:29 GMT