PEP 592 – 在简单 API 中添加“Yank”支持
- 作者:
- Donald Stufft <donald at stufft.io>
- BDFL-委托:
- Paul Moore <p.f.moore at gmail.com>
- 讨论地址:
- Discourse 帖子
- 状态:
- 最终版
- 类型:
- 标准追踪
- 主题:
- 打包
- 创建日期:
- 2019-05-07
- 决议:
- Discourse 消息
摘要
本 PEP 提案在简单仓库中添加标记特定文件下载为“yanked”的功能。Yanking 文件允许作者有效地删除文件,而不会影响那些已经固定到特定版本的用户的行为。
它还将简单仓库 API 的规范来源更改为 简单仓库 API 参考文档。
动机
每当一个项目发现 PyPI 上的特定版本可能存在问题时,他们通常希望阻止更多用户无意中使用该版本。然而,最明显的解决方案是删除仓库中的现有文件,这将影响那些遵循最佳实践并固定到特定项目版本的用户的行为。
这使得项目陷入困境,因为新项目可能会下载这个已知存在问题的版本,但如果他们采取任何措施来阻止这种情况,他们会影响到已经使用该版本的项目。
通过允许“yank”文件,但仍将其提供给明确要求它的用户,这使项目能够在最大程度上减少破坏性影响,同时仍然让那些已经解决问题或没有遇到底层问题的人正常使用。
可能发生这种情况的主要场景之一是当不再支持特定版本的 Python 时。 python-requires
元数据允许以不影响仍使用该 Python 版本的用户的方式放弃对 Python 版本的支持。但是,一个常见的错误是遗漏或忘记更新该元数据。当出现这种情况时,项目实际上只有三个选择
- 通过某种机制阻止该版本被安装(目前,唯一的方法是完全删除该版本)。
- 重新发布一个正常的版本,并使用更高的版本号,然后重新发布一个支持已被移除的版本,并使用更高的版本号,并附带正确的元数据。
- 不做任何操作,并说明使用较旧 Python 版本的用户必须手动排除该版本。
有了本 PEP,项目可以选择第一个选项,但使用一种不太可能影响到目前正在使用该项目的用户的机制。
规范
简单仓库中的链接 **可以** 包含一个 data-yanked
属性,该属性可以没有值,也可以包含任意字符串作为值。 data-yanked
属性的存在 **应该** 被解释为表示该链接指向的文件已被“Yanked”,并且通常不应被安装程序选择,除非在特定情况下。
data-yanked
属性的值(如果存在)是一个任意字符串,表示为什么该文件被 yanked 的原因。处理简单仓库 API 的工具 **可以** 将此字符串展示给最终用户。
一旦设置,yanked 属性不可变,可以在将来取消(取消后可以重新设置)。因此,API 用户 **必须** 能够应对一个 yanked 文件被“unyanked”(甚至再次 yanked)的情况。
安装程序
对于用户来说,理想的体验是,一旦一个文件被 yanked,当人类用户试图直接安装一个 yanked 文件时,它会像该文件已经被删除一样失败。但是,当一个人在一段时间前这样做,现在一台机器只是继续机械地按照最初的顺序安装现在被 yanked 的文件时,它会表现得像它没有被 yanked 一样。
安装程序 **必须** 忽略 yanked 版本,如果选择约束可以使用非 yanked 版本来满足,并且 **可以** 拒绝使用 yanked 版本,即使这意味着请求根本无法满足。实现 **应该** 选择遵循上述意图精神的策略,并防止对 yanked 版本/文件的“新”依赖关系。
这意味着由特定的安装程序决定如何最好地融入其安装程序的总体使用。但是,有两个建议的步骤
- 始终忽略 yanked 文件,除非它们是唯一一个匹配版本规范的文件,该规范“固定”到使用
==
(没有任何使它成为范围的修饰符,例如.*
)或===
的精确版本。否则,匹配此版本规范应该按照 PEP 440 的说明进行,比如本地版本、零填充等等。 - 始终忽略 yanked 文件,除非它们是唯一一个匹配锁定文件(例如
Pipfile.lock
或poetry.lock
)指定的要安装的文件。在这种情况下,在从某些输入文件或命令创建或更新锁定文件时, **不应该** 使用 yanked 文件。
无论安装程序选择哪种特定策略来决定何时安装 yanked 文件,安装程序 **应该** 在决定安装 yanked 文件时发出警告。该警告 **可以** 利用 data-yanked
属性的值(如果它有值)向用户提供更具体的反馈,说明为什么该文件被 yanked。
镜像
镜像通常可以以两种方式处理 yanked 文件
- 它们可以选择完全从其简单仓库 API 中省略它们,提供一个只显示“活动”、非 yanked 文件的仓库视图。
- 它们可以选择包含 yanked 文件,并另外镜像
data-yanked
属性。
镜像 **不得** 镜像一个 yanked 文件,而不也镜像它的 data-yanked
属性。
被拒绝的想法
简单仓库 API 的一个先前未公开的版本包含特定于版本的页面,比如 /simple/<project>/<version>/
。如果我们要添加这些页面,yanked 文件只能出现在这些页面上,而不能出现在无版本页面上。但这将大大降低简单 API 的可缓存性,并将直接影响我们扩展其规模以处理所有传入流量的能力。
本 PEP 的先前迭代将 data-yanked
属性作为布尔值。然而,人们决定允许使用字符串既简化了实现,又提供了额外的通用功能,允许项目提供一种机制来表明他们为什么在 yank 一个版本。
另一个建议是保留任意字符串中的某些语法,以便我们将来在需要时能够发展标准。然而,考虑到我们将来可以添加额外的属性,这个想法被拒绝了,而是倾向于在需要时使用额外的属性。
Warehouse/PyPI 实现笔记
虽然本 PEP 在文件级别实现了 yanking,但这很大程度上是由于简单仓库 API 的形式,而不是本 PEP 做出的特定决定。
在 Warehouse 中,用户体验将从 yank 或 unyank 整个版本的角度来实现,而不是作为对单个文件的操作,然后通过 API 作为单个文件被 yank 来公开。
其他仓库实现可以选择以不同的方式公开此功能,或者根本不公开它。
日志处理
每当一个版本被 yank 时,日志中将使用以下字符串模式之一记录一个条目
yank release
unyank release
在这两种情况下,标准日志结构都将指示哪个项目的哪个版本被 yank 或 unyank。
版权
本文件已进入公有领域。
来源: https://github.com/python/peps/blob/main/peps/pep-0592.rst
最后修改时间: 2024-06-18 17:55:29 GMT