PEP 643 – 包源分发版的元数据
- 作者:
- Paul Moore <p.f.moore at gmail.com>
- BDFL 委托:
- Paul Ganssle <paul at ganssle.io>
- 讨论至:
- Discourse 帖子
- 状态:
- 最终版
- 类型:
- 标准跟踪
- 主题:
- 打包
- 创建日期:
- 2020年10月24日
- 发布历史:
- 2020年10月24日,2020年11月1日,2020年11月2日,2020年11月14日
- 决议:
- Discourse 消息
摘要
Python 包元数据以标准格式存储在分发文件中,该格式在核心元数据规范中定义。然而,对于源分发版,虽然数据的格式已定义,但在源分发版中记录的数据一直存在很多不一致性。有关此问题的讨论,请参阅此处。
因此,元数据消费者无法依赖源分发版提供的数据,需要使用(代价高昂的)PEP 517 构建机制来提取元数据。
本 PEP 定义了一个标准,允许构建后端可靠地将包元数据存储在源分发版中,同时仍保留处理必须在构建时计算的元数据字段所需的灵活性。
动机
当前源分发版中元数据的存储方式存在许多问题
- 元数据存储的细节虽然已标准化,但不容易找到。
- 规范要求使用旧的元数据版本,并且未根据核心元数据规范的更改进行更新。
- 规范中无法区分“此字段已省略,因为其值在构建时才能知道”和“此字段没有值”。
- 核心元数据规范允许大多数字段可选,这意味着前一个问题几乎影响到每个元数据字段。
本 PEP 提议更新元数据规范,以允许记录预期“稍后填充”的字段,并更新源分发规范,以明确后端应使用该版本(或更高版本)的规范来记录 sdist 元数据。
基本原理
本 PEP 允许项目将源分发元数据值定义为“动态”。在此上下文中,称字段为“动态”意味着在生成源分发版时,该值尚未固定。动态值将在生成 wheel 时由构建后端提供,并且可能取决于构建环境的详细信息。
PEP 621 有一个类似的概念,即“动态”值将“稍后填充”,因此我们在此类比地使用相同的术语。
规范
本 PEP 定义了源分发版中指定的元数据值与从中构建的 wheel 中的相应值之间的关系。它要求构建后端清楚地标记任何将*不会*从 sdist 简单地不变复制到 wheel 的字段。
此外,本 PEP 将 PyPA 规范文档作为源分发格式规范的规范位置(收集了 PEP 517 和本 PEP 中的信息)。
一个新的字段 Dynamic 将被添加到核心元数据规范中。此字段将可多次使用,并且可以包含另一个核心元数据字段的名称。
当在源分发版的元数据中找到时,适用以下规则
- 如果一个字段*未*标记为
Dynamic,则从 sdist 构建的任何 wheel 中该字段的值*必须*与 sdist 中的值匹配。如果该字段不在 sdist 中,且未标记为Dynamic,则它*不得*出现在 wheel 中。 - 如果一个字段标记为
Dynamic,它可以在从 sdist 构建的 wheel 中包含任何有效值(包括完全不存在)。 - 如果后端可以确定某个字段是从构建时不会更改的数据生成的,则*不得*将其标记为
Dynamic。
后端*可以*在源分发版中记录他们计算出的标记为 Dynamic 的字段的值。然而,消费者*不得*将此值视为规范值,但*可以*将其用作关于 wheel 中最终值可能是什么的提示。
在源分发版之外的任何上下文中,如果一个字段被标记为 Dynamic,则表示该值是在 wheel 构建时生成的,并且可能与 sdist 中的值(或项目的其他构建中的值)不匹配。然而,后端不要求记录此信息,并且消费者*不得*假设缺少 Dynamic 标记具有任何意义,除非在源分发版中。
字段 Name 和 Version *不得*标记为 Dynamic。
由于它添加了一个新的元数据字段,本 PEP 将核心元数据格式更新到版本 2.2。
源分发版*应*使用创建时可用的最新版本核心元数据规范。
强烈鼓励构建后端仅在绝对必要时才将字段标记为 Dynamic,并鼓励项目避免需要使用 Dynamic 的后端功能。项目应优先使用静态值上的环境标记来适应安装位置的详细信息。
向后兼容性
由于此提案增加了核心元数据版本,因此它与现有的源分发版兼容,后者将使用较旧的元数据版本。工具可以通过检查元数据版本来确定源分发版是否符合本 PEP。
安全隐患
由于此规范纯粹用于存储旨在公开可用的数据,因此不存在安全隐患。
如何教授此内容
这是一种项目元数据的数据存储格式,因此通常对最终用户不可见。因此,无需教用户如何使用此格式。想要引用元数据的开发人员可以在 PyPA 规范中找到详细信息。
被拒绝的想法
- 与其将字段标记为
Dynamic,不如假定字段是动态的,除非明确标记为Static。这与当前提案在逻辑上是等效的,但它意味着字段是动态的是常态。在已知元数据是静态的情况下,打包工具可以更高效,因此 PEP 选择将动态字段作为例外,并要求后端“选择加入”使字段动态。
此外,如果动态是默认设置,那么在未来,随着越来越多的元数据变为静态,元数据文件将包含越来越多的
Static声明。 - 与其使用
Dynamic字段,不如添加一个特殊值来指示字段“尚未定义”。同样,这在逻辑上与当前提案是等效的。它使“动态”成为一个明确的选择,但需要一个特殊值。由于某些字段可以包含任意文本,选择这样一个值有些尴尬(尽管在实践中可能不是问题)。这种方法似乎没有足够的优势值得使用它而不是提议的机制。
- 对
Requires-Python的特殊处理。PEP 的早期草案需要对
Requires-Python进行特殊讨论,因为该字段缺少环境标记意味着可能难以要求其为静态。PEP 的最终形式不再需要这样做,因为允许动态字段的白名单概念被放弃了。 - 将
Dynamic的使用限制在允许字段的最小“白名单”范围内。由于 setuptools 接口的动态性质,这种方法可能很难让 setuptools 以向后兼容的方式实现。相反,现在的提案允许大多数字段是动态的,但鼓励后端除非必要,否则避免使用动态值。
未解决的问题
无
版权
本文档置于公共领域或 CC0-1.0-Universal 许可证下,以更宽松者为准。
来源:https://github.com/python/peps/blob/main/peps/pep-0643.rst