PEP 610 – 记录已安装发行版的直接 URL 来源
- 作者:
- Stéphane Bidoul <stephane.bidoul at gmail.com>,Chris Jerdonek <chris.jerdonek at gmail.com>
- 赞助商:
- Alyssa Coghlan <ncoghlan at gmail.com>
- BDFL 代表:
- Pradyun Gedam <pradyunsg at gmail.com>
- 讨论列表:
- Discourse 帖子
- 状态:
- 最终版
- 类型:
- 标准跟踪
- 主题:
- 打包
- 创建日期:
- 2019 年 4 月 21 日
- 发布历史:
- 决议:
- Discourse 消息
摘要
根据 PEP 440,可以通过名称和版本号或直接 URL 引用来标识发行版(请参阅 PEP440 直接引用)。安装后,名称和版本会捕获到项目元数据中,但目前无法获取通过直接 URL 引用识别发行版时使用的 URL 的详细信息。
本提案定义了其他元数据,由安装前端添加到已安装的发行版中,用于记录直接 URL 来源,以便那些检查已安装软件包数据库的使用者使用(请参阅 PEP 376)。
动机
此 PEP 的最初动机是允许使用“冻结”操作的工具,以便在更广泛的情况下重新创建 Python 环境。
具体来说,PEP 起源于解决 pip 问题 #609 的愿望:即在从直接 URL 引用安装的发行版存在的情况下,改进 pip freeze
的行为。它遵循了 discuss.python.org 上的一个帖子,讨论了实现它的最佳方案。
从直接 URL 引用安装
诸如 pip 之类的 Python 安装程序能够从软件包索引下载和安装发行版。它们还能够从指定源代码归档和版本控制系统 (VCS) 存储库的任意 URL 的需求中下载和安装源代码,如 PEP440 直接引用 中标准化的那样。
换句话说,存在两种相关的安装模式。
- 要安装的软件包指定为名称和版本说明符
在这种情况下,安装程序会在软件包索引中查找要安装的发行版(或者在 pip 的情况下,可选地使用--find-links
)。
- 要安装的软件包指定为直接 URL 引用
在这种情况下,安装程序会下载 URL 指定的任何内容(通常是 wheel、源代码归档或 VCS 存储库)并进行安装。在此模式下,安装程序通常会在临时目录中下载源代码,调用 PEP 517 构建后端(如果需要)生成 wheel,安装 wheel,然后删除临时目录。
安装后,用户请求下载软件包的 URL 在用户系统上不会留下任何痕迹。
冻结环境
Pip 还提供了一个名为 pip freeze
的命令,该命令检查已安装的 Python 发行版数据库以生成需求列表。此命令的主要目标是帮助用户生成需求列表,以便稍后以尽可能高的保真度重新安装相同的环境。
从 pip 19.3 版本开始,pip freeze
命令为每个已安装的发行版输出一行 name==version
(除了可编辑安装)。为了实现重新安装相同环境的目标,这需要 (name, version) 元组引用发行版的不可变版本。软件包索引(如 Warehouse)保证了不可变性。要使用的软件包索引通常是从安装程序的环境或命令行参数中知道的。
因此,此冻结机制对于安装模式 1(即当要安装的软件包指定为名称加版本说明符时)运行良好。
对于安装模式 2,即当要安装的软件包指定为直接 URL 引用时,name==version
元组显然不足以重新安装相同的发行版,并且冻结命令的用户期望它输出最初请求的 URL。
上述推理同样适用于除 pip freeze
之外的工具,这些工具会尝试从已安装的 Python 发行版数据库生成 Pipfile.lock
或任何其他类似格式。除非另有说明,否则本文档中“冻结”一词用作此类操作的通用术语。
对于应用程序集成者来说,从(VCS)URL 安装的重要性
对于应用程序集成者来说,能够可靠地安装和冻结 Python 发行版的未发布版本非常重要。例如,当开发人员需要部署依赖项的未发布修补版本时,通常会直接从包含修补程序的 VCS 分支安装依赖项,同时等待维护者发布更新版本。
在这种情况下,对于“冻结”来说,必须固定已安装的确切 VCS 引用(如果可用,则为提交哈希),以便创建具有尽可能高保真度的可重复构建。
VCS URL 可用的其他来源元数据
对于 VCS URL,只有在安装时才能获得其他来源信息,这些信息对内省和某些工作流程很有用。例如,当从 VCS URL 安装修订版本时,工具可以确定该修订版本是否对应于分支、标签或(在 Git 的情况下)ref。此信息可在检查已安装的发行版数据库时使用,以便向用户传达有关已安装版本的更多信息(例如,是否安装了分支或标签,如果是,则为分支或标签的名称)。这还可以让人知道是否可以使用标签形式构建 PEP 440 直接引用 URL,因为只有标签具有不可变性的语义。
在修订版本可变(例如分支和 Git ref)的情况下,了解此信息可以实现以下工作流程:例如,用户可以更新到他们正在跟踪的分支的最新版本,或者更新到他们正在本地审查的拉取请求的最新版本。相反,当修订版本是标签时,工具可以预先知道(例如,无需网络调用)不需要更新。
与 URL 本身一样,如果此信息在安装时 VCS 存储库可用时未记录,否则它将丢失。
关于“可编辑”安装的说明
pip 的可编辑安装模式大致允许用户出于开发目的将本地目录插入 sys.path。此模式被滥用来解决从 VCS URL 进行非可编辑安装的问题,即安装后会丢失来源跟踪。实际上,可编辑安装会隐式地将 VCS 来源记录在检出目录中,因此可以在运行“冻结”时恢复该信息。
此变通方法虽然有用,但很脆弱,会导致对可编辑模式的目的产生混淆,并且仅在可以使用 setuptools 安装发行版时才有效(即它不能与其他 PEP 517 构建后端一起使用)。
实施此 PEP 后,将不再需要使用可编辑安装来使 pip freeze 与 VCS 引用一起正常工作。
基本原理
此 PEP 指定在已安装发行版的 .dist-info
目录中添加一个新的 direct_url.json
元数据文件。
指定的字段足以重现源代码归档和 pip 支持的 VCS URL。它们也足以重现 PEP440 直接引用 以及 Pipfile 和 Pipfile.lock 条目。最后,它们足以记录已安装版本的、通过 VCS 检出存在而已可用的分支、标签和/或 Git ref 来源。
由于至少已经存在三种不同的方法来编码此类信息,因此此 PEP 使用字典格式,以便不对需求或锁定文件最终必须如何编码直接 URL 引用做出任何假设。有关此选择的更多讨论,另请参阅下面的 替代方案 部分。
已从 Ruby 的 bundler 手册中获取信息以验证它是否具有类似的功能,并为本规范中字段的选择和命名提供信息。
JSON 格式允许将来添加其他字段。
规范
此 PEP 指定在已安装发行版的 .dist-info
目录中添加一个 direct_url.json
文件,以记录发行版的直接 URL 来源。
此元数据文件的名称和语义规范来源是记录已安装发行版的直接 URL 来源文档。
安装程序从指定直接 URL 引用(包括 VCS URL)的需求中安装发行版时,**必须**创建此文件。
从其他类型的需求(例如名称加版本说明符)安装发行版时,**不得**创建此文件。
此 JSON 文件**必须**是一个字典,符合RFC 8259并使用 UTF-8 编码。
如果存在,它**必须**包含至少两个字段。第一个是url
,类型为string
。根据url
引用的内容,第二个字段**必须**是vcs_info
(如果url
是 VCS 引用)、archive_info
(如果url
是源代码归档文件或轮子)或dir_info
(如果url
是本地目录)。这些信息字段的值为(可能为空的)子字典,其中包含下面定义的可能键。
url
**必须**出于安全原因删除任何敏感的身份验证信息。
但是,URL 的用户:密码部分**可以**由环境变量组成,匹配以下正则表达式
\$\{[A-Za-z0-9-_]+\}(:\$\{[A-Za-z0-9-_]+\})?
此外,URL 的用户:密码部分**可以**是众所周知的、非安全敏感的字符串。一个典型的例子是在诸如ssh://git@gitlab.com
之类的 URL 中的git
。
当url
引用 VCS 存储库时,vcs_info
键**必须**作为字典存在,其中包含以下键
- **必须**存在
vcs
键(类型为string
),其中包含 VCS 的名称(即git
、hg
、bzr
、svn
之一)。其他 VCS **应该**通过编写 PEP 来修改此规范进行注册。url
值**必须**与相应的 VCS 兼容,以便安装程序可以将其在不进行转换的情况下传递给 VCS 的检出/下载命令。 requested_revision
键(类型为string
)**可以**存在,用于命名要安装的分支/标签/引用/提交/修订版等(以与 VCS 兼容的格式)。- **必须**存在
commit_id
键(类型为string
),其中包含已安装的确切提交/修订版号。如果 VCS 支持基于提交哈希的修订版标识符,则**必须**将此类提交哈希用作commit_id
,以便引用已安装的源代码的不可变版本。 - 如果安装程序可以发现有关请求的修订版的其他信息,它**可以**添加
resolved_revision
和/或resolved_revision_type
字段。如果在请求的 URL 中未提供修订版,则resolved_revision
**可以**包含已安装的默认分支,而resolved_revision_type
将为branch
。如果安装程序确定requested_revision
是标签,它**可以**添加resolved_revision_type
,其值为tag
。
当url
引用源代码归档文件或轮子时,archive_info
键**必须**作为字典存在,其中包含以下键
- **应该**存在
hash
键(类型为string
),其值为<hash-algorithm>=<expected-hash>
。**建议**仅对源代码归档文件哈希使用标准库的最新版本hashlib
模块无条件提供的哈希。在撰写本文时,该列表包括“md5”、“sha1”、“sha224”、“sha256”、“sha384”和“sha512”。
当url
引用本地目录时,dir_info
键**必须**作为字典存在,其中包含以下键
editable
(类型:boolean
):如果发行版以可编辑模式安装,则为true
,否则为false
。如果不存在,则默认为false
。
当url
引用本地目录时,它**必须**具有file
方案并符合RFC 8089。特别是,路径组件必须是绝对路径。在将相对路径转换为绝对路径时,**应该**保留符号链接。
注意
当请求的 URL 具有file://方案并指向碰巧包含 VCS 签出的本地目录时,安装程序**不得**尝试推断任何 VCS 信息,因此**不得**在direct_url.json
中输出任何与 VCS 相关的信息(例如vcs_info
)。
**可以**存在顶级subdirectory
字段,其中包含相对于 VCS 存储库、源代码归档文件或本地目录根目录的目录路径,以指定pyproject.toml
或setup.py
所在的位置。
注意
一般来说,安装程序应尽可能在生成direct_url.json
时保留在请求的 URL 中提供的信息。例如,应保留用户:密码环境变量,并且requested_revision
应尽可能忠实地反映在请求的 URL 中提供的修订版。但是,此信息会使用更精确的数据(例如commit_id
)进行**丰富**。
已注册的 VCS
本节列出了已注册的 VCS;扩展了有关如何使用vcs
、requested_revision
和vcs_info
的其他字段的 VCS 特定信息;在某些情况下,还提供了其他 VCS 特定字段。工具**可以**支持其他 VCS,尽管**建议**通过编写 PEP 来修改此规范进行注册。vcs
字段**应该**是命令名称(小写)。支持此类 VCS 所需的其他字段**应该**以 VCS 命令名称为前缀。
Git
主页
vcs 命令
git
vcs
字段
git
requested_revision
字段
标签名称、分支名称、Git 引用、提交哈希、缩短的提交哈希或其他提交式。
commit_id
字段
提交哈希(40 个十六进制字符 sha1)。
注意
安装程序可以使用git show-ref
和git symbolic-ref
命令来确定requested_revision
是否对应于 Git 引用。反过来,以refs/tags/
开头的引用对应于标签,而克隆后以refs/remotes/origin/
开头的引用对应于分支。
Mercurial
主页
vcs 命令
hg
vcs
字段
hg
requested_revision
字段
标签名称、分支名称、变更集 ID、缩短的变更集 ID。
commit_id
字段
变更集 ID(40 个十六进制字符)。
Bazaar
主页
vcs 命令
bzr
vcs
字段
bzr
requested_revision
字段
标签名称、分支名称、修订版 ID。
commit_id
字段
修订版 ID。
Subversion
主页
vcs 命令
svn
vcs
字段
svn
requested_revision
字段
requested_revision
必须与svn checkout
--revision
选项兼容。在 Subversion 中,分支或标签是url
的一部分。
commit_id
字段
由于 Subversion 不支持全局唯一标识符,因此此字段是相应存储库中的 Subversion 修订版号。
示例
direct_url.json 示例
源代码归档文件
{
"url": "https://github.com/pypa/pip/archive/1.3.1.zip",
"archive_info": {
"hash": "sha256=2dc6b5a470a1bde68946f263f1af1515a2574a150a30d6ce02c6ff742fcc0db8"
}
}
带有标签和提交哈希的 Git URL
{
"url": "https://github.com/pypa/pip.git",
"vcs_info": {
"vcs": "git",
"requested_revision": "1.3.1",
"resolved_revision_type": "tag",
"commit_id": "7921be1537eac1e97bc40179a57f0349c2aee67d"
}
}
本地目录
{
"url": "file:///home/user/project",
"dir_info": {}
}
以可编辑模式安装的本地目录
{
"url": "file:///home/user/project",
"dir_info": {
"editable": true
}
}
pip 命令示例及其对 direct_url.json 的影响
生成direct_url.json
的命令
- pip install https://example.com/app-1.0.tgz
- pip install https://example.com/app-1.0.whl
- pip install “git+https://example.com/repo/app.git#egg=app&subdirectory=setup”
- pip install ./app
- pip install file:///home/user/app
- pip install –editable “git+https://example.com/repo/app.git#egg=app&subdirectory=setup”(在这种情况下,
url
将是已克隆 Git 存储库的本地目录,并且dir_info
将存在,其中"editable": true
,并且不会设置vcs_info
) - pip install -e ./app
**不**生成direct_url.json
的命令
- pip install app
- pip install app –no-index –find-links https://example.com/
用例
“冻结”环境
诸如pip freeze
等从已安装 Python 发行版数据库生成需求的工具,**应该**利用direct_url.json
(如果存在),并优先于版本元数据,以生成更高保真度的输出。在存在vcs
直接 URL 引用时,**应该**优先使用commit_id
字段,以便尽可能地提供与最初安装版本的高保真度。如果其需求格式支持,鼓励工具也输出存在的tag
值,因为它具有不可变的语义。工具**可以**根据用户需求选择其他方法。请注意,此 PEP 的初始迭代没有尝试使包含可编辑安装或来自本地目录的安装的环境可重现,但它确实尝试使它们易于识别。通过通过此规范的
url
和dir_info
字段查找本地项目目录,工具可以实现适合其用例的任何策略。
向后兼容性
由于此 PEP 在 .dist-info
目录中指定了一个新文件,因此没有向后兼容性影响。
替代方案
PEP 426 source_url
现已撤回的 PEP 426 指定了一个 source_url
元数据条目。它也在 distlib 中实现。
它的目的是略有不同,用于 sdists。
此格式缺乏对 subdirectory
(pip 需求 URL 的选项)的支持。同样的限制也存在于 PEP440 直接引用 中。
它还缺乏对 URL 中用户:密码部分的环境变量 的明确支持。
在 PEP 440 中引入键/值扩展机制和对用户:密码环境变量的支持对于在此 PEP 中使用是必要的。
revision 与 ref
requested_revision
键保留而不是 requested_ref
,因为它是在各种 VCS 中更通用的术语,而 ref
对 git
具有特定的含义。
致谢
许多人帮助实现了此 PEP。Paul F. Moore 提供了摘要的核心内容。Alyssa Coghlan 建议使用 direct_url 名称。
版权
本文件置于公共领域或根据 CC0-1.0-Universal 许可证,以较宽松者为准。
来源:https://github.com/python/peps/blob/main/peps/pep-0610.rst
上次修改时间:2023-10-11 12:05:51 GMT