Pip: 迈向 PEP 518

创建于 2017-10-21  ·  101评论  ·  资料来源: pypa/pip

这个周末我不在家,但据我所知,需要讨论 PEP 518 并在 pip 中实施它。

我已经打开了这个问题,因为我找不到讨论发生的地方,如果是的话。 另外,把它放在一个不是 pypa-dev/distutils-sig 的地方会很好吗?

auto-locked maintenance

最有用的评论

通常,您需要在子进程内运行单独的 pip 安装,因为我相信pkg_resources之类的地方有缓存(尽管我在那里可能是错的)。

这并不意味着您需要调用pip ,但是您可以创建一个通过 CLI 序列化数据的 API,然后调用python -c "from pip._internals import coolapithing; coolapithing(sys.stdin.read())"并从标准输出读取更多数据。 可以通过使用这样的 API 将 pip 调用 pips 调用 pips 调用 pips 的递归解决方案转换为堆栈(因为所有递归也可以描述为堆栈),您实际上只是在制作一个私有 API这被称为一个过程。

我仍在计划阅读此线程(最近有一堆盘子在旋转!),但有一点:我们并没有真正的发布时间表,我们会在它准备好而不是在某个目标日期时发布。 我们有时会对我们想要发布的时间有一些大致的想法,但这并不是一成不变的。

所有101条评论

4799是很多争论发生的地方。 这主要是由以下原因引起的:

  1. 我知道 PEP 518 支持的唯一杰出阻止程序是 #4764(通过 https://github.com/pypa/pip/pull/4144#issuecomment-302711736)
  2. 然后#4799 出现了,我查看了它,看看我是否能理解@xoviat正在做的所有正在进行的工作。
  3. 在此过程中,#4647 作为发布阻止程序弹出,表示 PEP 518 支持已被破坏。

当我深入研究@xoviat在#4799 中所说的内容时,很明显我们在构建环境的递归构建方面遇到了一些问题(X 需要 Y 来构建,Y 需要 Z,......)虽然我'我仍然不清楚这些是实现错误、更深层次的设计问题,还是我们可以在没有太多问题的情况下推迟的讨厌的极端情况。

就个人而言,我正处于超出我的深度的地步。 我不明白@xoviat的实现来判断它是否需要,或者我们是否仍然只需要合并 #4764 并修复 #4647 以准备就绪。 我也不知道修复 #4647 有多么容易( @xoviat似乎在说我们需要合并 #4799 来修复 #4647,但这会带来自己的问题)。

这个周末我已经没有时间和精力继续讨论了,所以我现在要退出(至少一段时间)。 对我来说,关键是我们希望 PEP 518 支持 pip 10 的可接受水平。我希望有人给我一个感觉,我们是否快到了那里,或者我们是否还有几周的时间,所以我可以避免让人们因为 pip 10 即将到来而感到兴奋,然后才说要等到新的一年......

感谢@pfmoore 提供了非常有用的总结。

@ncoghlan @dstufft @xoviat我们可以把讨论带到这里吗? 在封闭的 PR 上做这件事对我来说感觉很奇怪。 ._.

肯定的事。

@pradyunsg我知道你没有时间。 但是您在获得 PR 批准方面比我更成功,所以如果您愿意,我将非常乐意带您了解当前的实施、它是如何工作的以及它存在的潜在问题。 我将解释我是如何解决一些(但不是全部)这些问题的,以及我对完整修复的想法(同样,如果没有完成,我可能会在 PEP 517 之后这样做)。 老实说,只要工作完成,我不在乎谁来做。

其实你是擅离职守,所以让我写一个总结:

pip具有对象层次结构,这在大多数 Python 项目中很常见。 这一切都启动了该命令,该命令创建对对象的新引用,该引用创建对较低对象的新引用。 它就像一棵树。

我将对象的“范围”定义为一种生命周期。 它是对象存在的持续时间。 现在,PEP 518 在pip的范围是WheelBuilder 。 PEP 518 环境设置为bdist_wheel ,然后bdist_wheel在该环境中运行,然后环境被拆除。

那么这有什么问题呢? 问题是 PEP 518 环境的范围需要等于或大于对setup.py的所有调用的范围。 更具体地说,它需要封装一个在setup.py调用期间存在的对象。 该对象是Requirement

您将遇到的第一个明显决定是:应该引用BuildEnvironment ,并且Requirement是一个很好的地方。 事实上,恕我直言,这是放置引用的最佳位置,因为当且仅当Requirement存在时才调用 $# setup.py 10$#$。

您可能会遇到的下一个问题是:我们如何安装BuildEnvironment要求? 我们可以掏出pip 。 这就是最初的实施者做出的决定。 但是这样做有一个问题: pip无法知道它进行了多少 shell 调用,因为每个pip都可以再次调用自己。 事实上,如果pip产生了太多的进程,一个带有循环依赖的恶意构建的包可能会导致某人的计算机崩溃。

另一个问题是我们应该调用什么shell? 这实际上比您想象的要棘手,因为坦率地说,获取命令行参数是您需要进行调用的 PITA。 因此,您可能无法传递用户传递给孩子的原始参数。 原始实施者使用的解决方案涉及使用finder ,但我认为您知道问题所在。

在没有某种可以在用户按下 ctrl+C 时杀死孩子的管理器类的情况下炮击自己的孩子不仅是错误的,而且是恶意的,尤其是当您不知道自己产生了多少进程时。 我个人不知道孩子们是否在当前的实施中死亡(这可能是 FUD),但如果他们不这样做,恕我直言,目前的实施是错误的(除了其他问题)。

该问题的一些可能解决方案如下:

  1. 如果你想让 PEP 518 出门,最好的选择可能是某种锁文件,它只允许最多 10 个锁左右,以确保 pip 不会无限增加。 然后,您可以将确切的要求与命令行参数一起传递给孩子。

  2. 我想在 PEP 517 之后实施的一个合适的解决方案是在install命令中直接初始化一个BuildEnvironmentManager类。 BuildEnvironmentManager将引用那里的所有对象( RequirementPreparerWheelBuilder等),并且只有一个方法: get_build_environment(requirement_set) 。 然后,您可以在RequirementPreparer上实现一个类似于set_build_environment_manager的方法,然后它可以使用它来获取构建环境。 BuildEnvironmentManager甚至可以检测同一环境的多次使用(最常见的是['setuptools', 'wheel'] )并在多次需要时提供相同的环境,这样您就不需要创建它(最初很常见没有pyproject.toml的项目)。 理想情况下,还会有一些 OOP 设计来尝试删除循环引用(不是微不足道的)。

@xoviat虽然它可能无法涵盖蓄意恶意的情况,但我认为构建缓存(即使在指定--no-binary :all:时也使用)不仅能够跟踪已完成的构建,而且还能够在-progress 的,是否足以确保构建依赖周期终止? 这将是您第一个建议的变体(对并发 pip 调用数量的跨进程限制),但重新表述为:

  1. 一台机器上只允许一个进程同时构建同一个包
  2. 有一个顶级“构建 ID”,pip 会向下传递到它产生的任何子构建(例如,顶级进程的 PID 与正在构建的包的名称相结合)
  3. 如果构建缓存指示正在由不同的构建 ID 构建某些内容,则等待该构建完成
  4. 如果构建缓存表明已经为相同的构建 ID 构建了某些东西,则通过报告循环依赖的错误退出,并指示构建工作需要--binary <name>

pip还需要实施@pfmoore的建议,即从需要setuptoolswheel的默认逻辑中免除setuptoolswheel wheel作为构建依赖,否则隐式构建依赖注入将固有地触发循环依赖检测逻辑。

使用磁盘来避免不得不找出 OOP 设计问题并不是一个坏主意。 这就像完全正确实施 PEP 518 和一起破解某些东西之间的中间选项。

它还可以很好地与容器化环境和 chroot 交互,因为我们可以使用操作系统级别的工具来保持不同的 Python 级别的构建相互隔离,所以 pip 只需要弄清楚如何确保它自己的子进程互相合作。

@xoviat感谢上面的总结。 正如我所说,我已经达到了我对这方面代码的理解的极限,你的解释对我帮助很大。

我之前实际上并没有看过#4144 的代码。 我只是这样做了,我真的不希望它被运送。

完全正确地实施 PEP 518 并且只是一起破解一些东西。

老实说,我认为归结为这一点。 完全正确地实施 PEP 518 是一项任务,如果我们这样做,可能会/可能会延迟 pip 10 a(公平)位。

我认为这里的一个安全的中间立场是要求构建依赖项作为轮子提供。 这样,我们可以避免递归问题,因为不需要通过这个过程来构建构建依赖项(及其所有依赖项)。

这听起来如何?

它是受限制的,但我认为受限制的第一次实施比如果你不小心第一次实施,你可以自己开枪。

完全正确地实施 PEP 518 是一项任务,如果我们这样做,可能会/可能会延迟 pip 10 a(公平)位。

感谢您确认 - 那是我的恐惧。

但是,现在我困惑,因为我认为至少部分 PEP 518 已经在 master 中了。 具体来说,据我所知,#4647 演示了 master 中 PEP 518 支持中的一个错误 - 很明显我们已经有了一些东西,因为它是不正确的......

所以我们必须做点什么,似乎选项是:

  1. 撕掉我们目前对 PEP 518 的支持。
  2. 整理我们所拥有的并提供部分支持。
  3. 在我们发布 pip 10 之前完全实施 PEP 518。

正如你所说的 (3) 意味着在 pip 10 之前有很长的延迟,我们还有其他我非常希望看到的修复程序(Unicode 修复程序是我们经常解决的问题)。 所以我对此并不热衷。 您没有提到 (1),我不确定这是否是因为您认为我们没有 PEP 518 支持,或者您是否认为不支持它。 就个人而言,我不喜欢这个想法 - 这是一个倒退,如果它很难正确实施,它会发出关于 PEP 本身的负面信息。 但我认为我们应该明确拒绝它。

您对 (2) 的建议,即我们发布仅支持轮子作为构建依赖项的 PEP 518 版本(我们仍然需要修复 #4647,因为它的演示使用的是轮子的构建依赖项)似乎是合理的,从某种意义上说,它对我们来说是切实可行的。 我的主要保留意见是,我不知道该限制对于想要使用 PEP 518 的人来说会有多大问题。

所以我想我觉得我们无论做什么都被卡住了,但是部分支持只覆盖轮子作为构建依赖项是最好的选择:-(

PEP 作者(在 https://github.com/pypa/pip/pull/4799#issuecomment-338331267 和 https://github.com/pypa/pip/pull/4799#issuecomment-338332575 中回答我的问题https://github.com/pypa/pip/pull/4799#issuecomment-338325354)非常明确,完全 PEP 支持需要构建任何构建依赖项,所以它必须只是一个权宜之计。

但执行此操作的不是我,所以我很乐意接受执行此操作的人的判断。 我所做的一件事是创建 #4803 并将其标记为发布阻止程序,以提醒我们应该记录我们如何偏离规范,如果需要的话。

(对于这个问题,题外话,但我可以建议我们在开始实施 PEP 517 时小心不要犯同样的错误吗?让我们确保在深入编码之前了解所有实施含义 - 我的直觉是不是 PEP 517 将是一个比 PEP 518 更复杂的设计问题......)

当谈到“从源代码构建一切”的角度时,我最熟悉发行版,我们肯定将“引导 buildroot”的过程与常规包构建的过程分开。 从源代码完全自动引导很困难,因为你最终不得不做一些事情,比如引导你的 C 编译器。

所以对于 pip,我认为构建依赖项总是可以从轮文件安装是合理的。 您可以在 10.x 后引入的改进是拥有一个不同于常规车轮缓存的构建缓存,这样缓存的用户可以确定其中的所有车轮都是在受控环境中构建的,而不是从 PyPI 下载的或其他索引服务器。

就个人而言,我不喜欢这个想法 - 这是一个倒退,如果它很难正确实施,它会发出关于 PEP 本身的负面信息。

我不一定同意这一点。 pip 很难正确实现。 但是 PEP 中所述的 pip 是人们将要使用的唯一前端之一。 我认为这是我们作为语言实现者的工作,而 pip 确实是人们用来打包他们的 python 项目的一种语言,它可以尽可能简单地创建一个构建系统,而不必考虑所有这些困难的问题。 对他们来说,它应该无缝地工作,因为我们已经完成了艰苦的工作。

我认为这里的一个安全的中间立场是要求构建依赖项作为轮子提供。

实际上,这正是#4799 所做的。 如果您愿意,我可以恢复该分支,然后您可以分叉并将其作为 PR 提交。

尽管如此,(2) 的实现方面的两件事仍然存在——正如@xoviat在上面指出的那样:

  1. 弄清楚如何创建子流程(arguments et al)
    我认为应该是可行的。

  2. 要安装的软件包版本。
    这可能应该在同一个父进程中完成,尽管鉴于当前解析器代码仍然与pip._internal.operations.prepare中的代码交织在一起,我不确定这将如何发生。 这周的某个时候我会调查一下。

我不确定谁有时间做这些。


如果很难正确实施,它会发出关于 PEP 本身的负面信息。

正确实施可能并不难。 只是以今天 pip 的代码库的方式,在 pip 中实现并非易事——在奇怪的地方会发生一些事情,我认为如果将其清理干净,那将是相当微不足道的。

您没有提到 (1),我不确定这是否是因为您认为我们没有 PEP 518 支持,或者您是否认为不支持它。

我认为退出不是一种选择。

现在我想一想——在 pip 10 中发送 PEP 518 有多重要? 我觉得如果它可以推迟到下一个主要版本,那将是简单的(除了作为摆脱这种情况的简单方法)并且 517 + 518 都可以在一个大版本中登陆。 这感觉很干净,我不会说这不是要走的路。

@dstufft @xavfernandez 的想法?


@ncoghlan的构建缓存想法对我来说听起来是个好主意,尽管我不确定我是否理解它的所有含义。


如果您愿意,我可以恢复该分支,然后您可以分叉并将其作为 PR 提交。

我可能没有时间,即使我有,我也可能不会重用任何现有的提交。 但是恢复该分支不会受到伤害。 :)

我的主要保留意见是,我不知道该限制对于想要使用 PEP 518 的人来说会有多大问题。

我们已经进行了确切的讨论,只是您可能甚至都不知道。 这种情况是情况 X。在设置构建环境之前调用 egg_info 是情况 Y (#4799)。

但执行此操作的不是我,所以我很乐意接受执行此操作的人的判断。

我想这意味着#4799 又回到了桌面上吗? 只要它通过了所有的测试并且做它声称做的事情?

啊,那些 X 和 Y 又回来困扰我了 :wink: 是的,我说我对这两个案例的相对可能性没有感觉。 我知道您是说非轮子的构建要求非常罕见,我们可以忽略这种情况。 基本上,我们之间的一票“没关系”和一票“不知道”也是如此。 我并不是要阻止这个选项,只是说我的直觉极限在哪里,就是全部。

@xoviat我有几个问题。 如果你能在做新的 PR 之前回答他们,那就太好了。 :)

  • 您将如何确定安装了哪些软件包?
  • 您是否要限制为仅二进制构建依赖项?

我参与过很多科学项目,所以可能是我有偏见。 但是我可以喋喋不休地列出一系列具有轮式构建依赖项的项目,而且我真的想不出一个具有源依赖项的项目。 也许我错了。

@rgommers如果PEP 518 在下一个pip 中仅支持可用作轮子的构建依赖项,您会同意吗?

您将如何确定安装了哪些软件包?

子流程完全按照指定的方式获取需求列表。 这样它就会通过解析器。

您是否要限制为仅二进制构建依赖项?

是的,这实际上就是测试失败的原因。 测试中的构建依赖不是轮子。

现在我想一想——在 pip 10 中发送 PEP 518 有多重要? 我觉得如果它可以推迟到下一个主要版本,那将是简单的(除了作为摆脱这种情况的简单方法)并且 517 + 518 都可以在一个大版本中登陆。 这感觉很干净,我不会说这不是要走的路。

对于我们是否会让任何人有时间为 pip 11 做 PEP 517 和 518,我们有什么感觉? 我并不乐观。 在我看来,它们都是一大块工作,而且我们也正在进行解析器工作。 虽然我不赞成将 pip 比必要的时间延长 10,但我同样不喜欢在发布一系列本质上是次要版本的同时让我们所有的主要功能计划漂移。

换句话说,说“让我们发布一个 pip 10 版本”促使 PEP 518 工作的活动重新抬头。 如果我们从 pip 10 中删除它,我将专注于为发布做好准备,我怀疑 PEP 518 很可能再次失去动力。 是什么让事情再次活跃起来? @xoviat一直致力于实施,但他在试图让我们其他人了解他一直在努力解决的问题时遇到了问题。 我不想让他再次在没有反馈的情况下工作。

我们可以做的是发布一个“pip 9.1”,其中仅包含我们准备好的增量修复,并保留版本号“pip 10”以实现(至少一个)正在筹备中的 3 个重要功能。 但如果我们这样做,我想尝试[1] 承诺在 2018 年第一季度发布 pip 10。作为一种方法,我可以接受。 但是,有没有人知道退出我们目前对 master 的部分支持会涉及什么? 或者记录我们拥有的东西以及它的限制是什么(这样人们就不会在假设它已经完成的情况下尝试使用它,遇到错误并提出我们必须用“这个功能尚未完成,对不起,但等待点子来回应”的问题10")? 我们只是将一大块工作换成不同的工作吗?

[1] 在我们所能提供的志愿者资源极其有限的情况下,我们可以致力于任何事情。

我参与过很多科学项目,所以可能是我有偏见

谢谢,有时很难了解人们的背景。 如果你熟悉科学项目,那会大大减轻我的担忧。

我们可以做的是发布一个“pip 9.1”,其中仅包含我们准备好的增量修复,并保留版本号“pip 10”以实现(至少一个)正在筹备中的 3 个重要功能。

我真的很喜欢这个。 +1 点 9.1.0 而不是点 10.0.0

我想尝试[1] 承诺在 2018 年第一季度发布 pip 10。作为一种方法,我可以接受。

我有一个非常有趣的脑电波——pip 在 2018 年 10 月 12 日满 10 岁。那将是发布 pip 10.0.0 的完美日期。 这是一个完全不同的时间线。 我并不是说我们应该将白鲸功能推迟到那时,但我的某些部分真的希望这个版本号和年龄的东西也能重合。

我怀疑 PEP 518 很可能再次失去动力。

我会尽我所能确保它不会。 希望@xoviat也愿意。 :)

有没有人知道退出我们目前对 master 的部分支持会涉及什么?

我不介意明天看看这个。 由于@dstufft是在#4144 上评论的人,我认为他对此的意见很有价值。

注意 - 我不想在未经@dstufft@xavfernandez同意的情况下做出任何激烈的事情——所以让我们也看看他们要说什么。

@dstufft一天没有足够的时间。 他还必须确保仓库不会倒塌。

让我们也看看他们要说什么。

是的,请。 :)

从用户体验的角度来看:全面对抗“信任信任”攻击真的很痛苦 [1],而且你会发现很多人说“我从源代码编译所有内容”实际上并没有这样做——在他们的流程中的某个地方将是一个引导步骤,他们信任由其他人提供的二进制文件(例如运行时环境和来自他们的操作系统提供商的构建工具链),或者来自他们自己的上一代平台(例如新版本的 Fedora 和RHEL 是从以前版本的 Fedora 和 RHEL 中获得的,它们并不是完全从头开始的)。 即使是像 Gentoo 这样的基于源代码的 Linux 发行版也从安装程序开始,为您提供一个包含 Linux 内核、C 编译器、硬件驱动程序等的工作构建环境。

所以我认为 pip 10 说--no-binary :all:仅适用于运行时依赖项,而不是构建依赖项是完全合理的。 如果人们想从源代码显式构建他们的 buildroot,他们仍然可以 - 只是 pip 10 不会为他们隐式自动化它,因为允许为您的构建依赖项进行隐式源构建所涉及的固有递归引导问题。

为了让人们表明他们希望构建环境完全预配置,如果需要隐式二进制引导作为源构建的一部分,添加单独的--no-implicit-builddeps选项以使安装完全失败是合理的. 这样,试图确保所有内容都是从源代码构建的(包括构建依赖项)的人可以执行以下操作:

pip install --no-binary :all: --no-implicit-builddeps -r build-requirements.txt
pip install --no-binary :all: --no-implicit-builddeps -r requirements.txt

并根据需要定义尽可能多的不同安装组,以达到第一个不需要除 CPython 和预安装的任何非 Python 构建工具链之外的任何东西的程度。

该概念的一个潜在的未来补充是允许人们说--buildenv <path>来指定一个预配置的构建环境以用于任何所需的源构建,而不是在一个隔离的环境中进行每个构建。 但是,我不会尝试将其纳入 pip 10 - 我建议将 10.x 限制为“允许二进制构建依赖项”的快乐路径和“如果需要二进制构建依赖项则使构建失败”的替代选项并且在当前运行的解释器中尚不可用”。

[1] https://www.schneier.com/blog/archives/2006/01/countering_trus.html

我想到了另一种选择,这似乎是合理的并且不需要太多重构:本质上是在构建环境设置时使用多线程来暂停主线程。 这个想法有点像这样:在install.py中,你会有一个BuildEnvironmentManager

class BuildEnvironmentManager(Thread):
    '''Has references to literally everything (cache, resolver, etc.)'''
    def run(self):
        while True:
            requirement_list, future = self.build_environment_queue.get()

            # install the requirements using all of the things
            # that we have

            # then put the build environment in the future
            future.put(BuildEnvironment())

然后你会有另一个文件,(我使用 backend.py 因为它不够满,可能会在其中使用更多东西,它位于树的下端):

class Future(Queue):
    pass

class BuildEnvironmentQueue(object):
    def __init__(self):
        self._queue = Queue()

    def request_build_environment(self, requirement_list):
        f = Future()
        self._queue.put((requirement_list, f))
        return f.get()

    def get():
        return self._queue.get()

在操作/prepare.py 中:

# This call will put the thread to sleep until we have a build environment
# with the requirements installed
self.build_environment_queue.request_build_environment(requirement_list)

这样做的好处是需要最少的重构,具有序列化的BuildEnvironmentManager (因此可以优化构建环境,并且您可以确切地知道在单个对象中发出了哪些请求)并将所有内容都包含在一个进程中(因此最坏的情况是死锁)。 当然,需要为其他线程禁用日志记录,但这并不是什么大问题。

回答我自己关于基于 queue.Queue 的方法的问题:最好避免依赖 concurrent.futures,因为使用它需要在 Python 2.7 中提供https://pypi.org/project/futures/

在不了解pip代码库的情况下,将构建环境管理整合到一个地方的想法似乎仍然是一个有吸引力的选择。

该方法不需要concurrent.futuresFuture只是一个更具描述性的包装器。

唯一需要原始的是队列: https ://docs.python.org/2/library/queue.html

我想我们可以将这些行移到BuildEnvironmentManager中。

我参与过很多科学项目,所以可能是我有偏见。 但是我可以喋喋不休地列出一系列具有轮式构建依赖项的项目,而且我真的想不出一个具有源依赖项的项目。 也许我错了。

好吧,对于一个不是[Windows,macOS,Linux],IIRC的所有操作系统, manylinux1都没有涵盖这些操作系统。

@rgommers如果PEP 518 在下一个pip 中仅支持可用作轮子的构建依赖项,您会同意吗?

不是我的电话,但我会对这里的任何进步感到高兴。 无论如何,PEP 518 支持是可选的,因此它仅在 pip 10 中可用的轮子(我会说覆盖> 90%的情况)时才起作用,这仍然是一个显着的改进。

请注意,即使在 PyPI 上不允许使用轮子的平台仍然会有一个本地轮子缓存,这意味着即使 pip 不能隐式引导事物,它仍然可以将它们打印出来并说“以某种方式安装这些构建依赖项,然后这将起作用”。

但是,有没有人知道退出我们目前对 master 的部分支持会涉及什么?

我调查了这个; 似乎不太难。 如果我们决定走这条路,我很乐意为它做 PR。

+1 点 9.1.0 而不是点 10.0.0

我终于有时间正确阅读 distutils-sig 线程并查看相关的 PR 和讨论(#4351、#4144、#4799 和其他一些)。 我现在认为自从我们宣布了 10 点以来; 这就是我们应该做的,部分 PEP 518 支持——没有 9.1.0。

这个版本号和年龄的东西要重合

真可惜。 :(

@ncoghlan也许这条评论被忽视了——https ://github.com/pypa/pip/pull/4799#issuecomment -338416543

如果它没有,如果你能解释为什么它不起作用,那就太好了,因为我有点理解这种设置,并且肯定愿意更多地了解它。 :)

@pradyunsg我认为这主要是可行的,因为它是构建缓存想法的特定实现。 它没有涵盖的一个方面是构建依赖循环,因为它缺少一种检测“我只是被要求构建我已经尝试构建的东西”的方法。

请注意, pip 不需要神奇地解决依赖循环 - 它只需要检测它们并在发现依赖循环时立即失败,而不是实际进入无限循环。

它不包括构建依赖循环,

仅二进制构建依赖项不会发生这种情况?

@pradyunsg链接的评论是关于允许为构建依赖项构建源代码的方式,这意味着循环依赖项成为一个潜在的问题。 如果我们需要二进制依赖,那么pip可以暂时只依赖现有的轮子缓存。

啊对。 谢谢! :)

我赞成 pip 10 的部分 PEP 518 实现仅限于二进制构建依赖项(或已经在 pip 轮缓存中可用),如果这是我们设法包含的全部内容。

我还没有阅读整个线程,但我只想指出限制二进制构建依赖项的一个副作用是,在许多情况下,您的构建部门中不可能有 C 依赖项。 是的,我们在 Windows、macOS 和一些 Linux 版本上有二进制轮子,但我们没有:

  • 任何不使用 glibc 的 Linux(Docker 内部的 Alpine Linux 是一种流行的)。
  • 任何不是 Linux 的 *nix 操作系统,如 FreeBSD 等。

这意味着任何基于 CFFI 的项目要么无法使用 PEP 518,要么无法在这些平台上卸载。

这可能已经提出来了! 稍后我将阅读此主题。

@dstufft没错。 但我们建议的是使用 pip 缓存是一种选择。 因此,您可以首先pip wheelpip install构建依赖项,然后将它们存储在缓存中。

这可能已经提出来了!

不。 :)

这意味着任何基于 CFFI 的项目要么无法使用 PEP 518,要么无法在这些平台上卸载。

的确。 :-(

在我的脑海中解决这个问题的方法是我们可以让 PEP 518 行为选择加入——如果有pyproject.toml文件,我们使用隔离 + 构建环境,否则回退到使用setup.py的当前行为

稍后我将阅读此主题。

请做。 :)

我和唐纳德的评论完全相同。 我对这个线程的理解是 binary-only 是暂时的,因为没有时间为 pip 10 实现它。对吗?

如果它被提议为永久决定,那么当然是-1。

我和唐纳德的评论完全相同。 我对这个线程的理解是 binary-only 是暂时的,因为没有时间为 pip 10 实现它。对吗?

这是正确的。 pip应该支持源依赖,但我们缺乏人力。

在我看来,解决这个问题的方法是我们可以让 PEP 518 行为选择加入——如果有 pyproject.toml 文件,我们使用隔离 + 构建环境,否则回退到使用 setup.py 的当前行为。

我重新阅读了这篇评论,我在这里不同意。 PEP 518 支持不应该是可选的,(出于与 PEP 517 相关的实施原因)恕我直言,但项目不应在这些平台上变得可卸载。

更具体地说,您正在安装的特定项目不应该决定您是否获得 PEP 518。这应该取决于您的构建依赖项是作为轮子还是在缓存中可用。 此外,如果我们只是吐出如下消息,我们也可以强制这些平台支持 PEP 518:

Error: build dependency X is not in the pip cache. Run "pip install X" before installing Y.

总结一下我自己的观点:

  1. 我将“对构建依赖项的隐式构建支持”视为 pip 10 中的一个临时限制,以使某些类别的问题(例如构建依赖项循环)在该功能的第一次发布迭代中无法遇到。 可插拔构建后端支持的未来迭代可以允许为构建依赖项进行隐式源构建,同时采取适当的措施来避免一旦您允许出现的新问题。
  2. 现在,在错误消息中发出相关的python -m pip wheel X Y Z命令而不实际运行构建是一个足够的解决方法,因为它确保 pip 不会无意中分叉炸弹机器。
  3. 隔离构建可能不应该是默认设置,除非正在构建的特定轮子具有pyproject.toml文件,或者从命令行明确请求隔离构建。 这是一个向后兼容性问题,因为现有项目将期待非隔离行为。 一旦隔离构建可用于一个或两个版本,并且解决了它们的任何可用性问题,那么它们通常可以成为默认值(可能使用命令行选项来指定要使用的特定构建环境,而不是隐式生成隔离那些)

@ncoghlan只是提醒您:没有默认的构建隔离意味着没有 PEP 517(至少在我的方法中),因为只有最新版本的 setuptools 支持它(我们需要安装更新的 setuptools,不管这个人的计算机)。 实际上,我认为这可能会使 PEP 517 至少延迟一年,因为它将大大增加实施它所需的工作量(需要 PEP 517 和非 PEP 517 代码)。

这是一个向后兼容性问题,因为现有项目将期待非隔离行为。

大多数人都有运行pip install X然后运行pip install Y的 CI 脚本。 这些项目需要添加一个pypproject.toml 。 但是添加pyproject.toml并没有那么多工作,如果需要,我们可以添加一个命令行标志来禁用构建隔离。

如果项目在 pip 10 中没有pyproject.toml ,我们至少应该发出警告(看起来无论如何都不会有 PEP 517 支持)。

@xoviat “调整起来不会有那么多工作”不是向后兼容性的工作原理。 如果是这样,pip 现在会切换到--user作为默认的非 venv 安装模型 :)

就 PEP 517 而言,您不能在添加pyproject.toml文件的情况下将 PEP 517 作为软件包发布者,因此如果仅setup.py项目没有获得 PEP 517 支持,那也没关系默认情况下。

你可以发出警告吗?

如果当前运行良好的构建仅仅因为 pip 升级而开始吐出警告,我会认为这是一个问题,即使项目本身及其任何依赖项都没有改变。

PEP 518 和 517 被刻意设计为对现有项目造成中断,其中所有涉及的发布者继续仅依赖设置工具。

即使对于基于 setuptools 的项目, pip的目标是整合回单个 PEP 518 构建路径确实是有意义的,但是这样做的时间是独立构建已经看到一个或两个实际使用价值的发布之后,而不是在完全支持它们的第一个版本中。

我和唐纳德的评论完全相同。 我对这个线程的理解是 binary-only 是暂时的,因为没有时间为 pip 10 实现它。对吗?

是的。 确切地。


即使对于基于 setuptools 的项目,pip 旨在整合回单个 PEP 518 构建路径确实是有意义的,但是这样做的时间是在隔离构建已经看到一个或两个版本的实际使用价值之后,而不是在第一个版本中完全支持他们。

+1

我认为我们的目标应该是删除旧的路径,比如 2 个主要版本。 当 pip 获得完整且适当的 PEP 518 支持时; 我们应该弃用旧的构建逻辑并根据标准弃用政策将其删除。

我同意尼克的总结和...

因为它将大大增加实施它所需的工作量

不。我不认为以这种方式实施 PEP 518 有任何重大障碍。 我在https://github.com/pypa/pip/pull/4799#issuecomment -339219397 上做了一个简短的评论,关于如何在 pip 中实现它。


我们想做的是为人们提供从旧到新的干净过渡。 因此,我们需要保持当前 pip 9 安装逻辑不变——这将基本上支持我们目前以我们所做的确切方式所做的一切。

在存档中放入pyproject.toml文件意味着软件包选择加入新标准并愿意测试对新行为的支持——通过隔离和仅二进制构建的构建环境-依赖项(现在)。

不。我不认为以这种方式实施 PEP 518 有任何重大障碍。

在这里讨论 PEP 517。 对困惑感到抱歉。

我们必须运行两次测试来检查两个代码路径。 嗯,PEP 517 可能被推迟了。

国际海事组织,

  1. 如果项目没有pyproject.toml的警告听起来是个非常糟糕的主意。 毕竟,目前 PyPI 上 99% 的项目都没有pyproject.toml ,我们不能向最终用户发送垃圾邮件,警告他们无能为力(除了向项目报告问题(s ). 我错过了什么吗?
  2. 我不相信 PEP 518 中根本没有提到构建隔离。这是 pip 想要包含一段时间的附加功能,但它与 PEP 518 支持无关,除了巧合的事实,即实施了相同的 PR两者(AFAIR)。 因此,如果构建隔离是这里给我们带来问题的原因,我可以接受最初只有 PEP 518,并将隔离作为第 2 阶段添加。不过,我将把这个决定留给实现事物的人。

我错过了什么吗?

不。

我对最初只有 PEP 518 并添加隔离作为第 2 阶段感到满意。

我认为我们应该做 PEP 518 并一起构建隔离,因为这是让人们切换到隔离构建的好方法。

虽然 PEP 518 和 PEP 517 都不需要隔离构建,但 PEP 517 出于合理的原因推荐它们: https ://www.python.org/dev/peps/pep-0517/#recommendations -for-build-frontends-non-normative

如果没有本地二进制工件缓存,孤立的构建环境是不切实际的,但是一旦你拥有其中一个(就像pip现在所做的那样),它们就更可行了,因为:

  1. 在大多数安装中,您甚至不需要首先进行源代码构建
  2. 当您确实需要进行源代码构建时,您通常会从缓存中设置构建环境

同时,独立的构建环境确实需要发布者做更多的工作,因为它们意味着有缺陷的元数据会破坏发布者自己的构建,需要他们明确地说“我的构建依赖项没有完全声明”,以便做一个构建。

因此,从一开始就隔离基于pyproject.toml的构建提供了一个自然的切换点,因为整个 PEP 是关于提供一种方法来清晰一致地声明构建依赖与运行时依赖。 这意味着从setup.py转换过来的人可能会这样做,因为他们关心做那种事情,而刚开始新项目的人只会把它视为包装工具迫使他们跳的另一个圈通过。

因此,在开始编写代码之前,我想确认几件事:

  • PEP 517 支持不是 pip 10 的障碍
  • PEP 518 在 10 点

    • 通过pyproject.toml选择加入

    • 仅支持仅二进制构建依赖项

    • 隔离构建

PEP 517 不能成为 pip 10 的阻止者,因为它还没有准备好,并且在这一点上没有明确的前进道路(有前进的道路但尚不清楚)。

我有一个评论和问题来回应@xoviat评论,这里总结了实施挑战以及快速阅读这个帖子之后。

首先,关于事情可能爆炸的递归问题,通常任何递归函数都可以“转换”为迭代函数。 我想知道这种方法是否可以通过提供更多控制来提供帮助。

其次,与从 Python 中调用 pip 函数相比,shelling out 买了什么? 是否有任何原因无法创建/重构内部 API 函数来完成任何试图实现的目标? 这应该在调用调用时提供更大的灵活性(与 CLI 参数相比)。 这还可以通过允许更轻松地管理整个过程的状态来提供更多控制。

是否有任何原因无法创建/重构内部 API 函数来完成任何试图实现的目标?

其次,与从 Python 中调用 pip 函数相比,shelling out 买了什么?

它赢得了我们目前没有的时间。 pip已经落后于它的发布时间表。

首先,关于事情可能爆炸的递归问题,通常任何递归函数都可以“转换”为迭代函数。

我不是反递归。 我反对过程递归。 我认为如果你想使用 100% 的 CPU(好吧,在 Python 中是 20%)很好,但最终用户需要能够打开任务管理器并杀死最多 15 个进程。 对我来说,可能导致流程爆炸的情况是不可接受的。

不过,这并不能回答为什么它会赢得时间的问题。 是什么让创建一个做同样事情的内部 API 函数变得困难?

在任何情况下,如果脱壳解决了某些特定问题,使这种方法更容易的一种可能性可能是暂时公开一个私有/内部 CLI 命令,以便更容易传递所需的任何信息(例如,它甚至可以是一个序列化的 Python 对象, 等等)。

不过,这并不能回答为什么它会赢得时间的问题。 是什么让创建一个做同样事情的内部 API 函数变得困难?

如果你认为这很容易,那就继续吧。 我不是讽刺地说:请继续,因为它会解决所有问题。

我不认为这很容易。 我问这个问题是为了深入了解为什么它很难。 (我假设您已经考虑过这一点,因为您说这会节省时间。)

通常,您需要在子进程内运行单独的 pip 安装,因为我相信pkg_resources之类的地方有缓存(尽管我在那里可能是错的)。

这并不意味着您需要调用pip ,但是您可以创建一个通过 CLI 序列化数据的 API,然后调用python -c "from pip._internals import coolapithing; coolapithing(sys.stdin.read())"并从标准输出读取更多数据。 可以通过使用这样的 API 将 pip 调用 pips 调用 pips 调用 pips 的递归解决方案转换为堆栈(因为所有递归也可以描述为堆栈),您实际上只是在制作一个私有 API这被称为一个过程。

我仍在计划阅读此线程(最近有一堆盘子在旋转!),但有一点:我们并没有真正的发布时间表,我们会在它准备好而不是在某个目标日期时发布。 我们有时会对我们想要发布的时间有一些大致的想法,但这并不是一成不变的。

最终,尽管 Python 具有最大的递归深度,以确保事情不会失控。 如果我们采用这种方法,我们需要实施它。

是的,基于堆栈的方法可以非常有效地深入(比依赖循环之外的任何东西都更深,例如,我们可以拥有依赖于每个包的东西并且仍然很好),主要的事情要做的是检测循环。

进行循环检测的一种相当天真和简单的方法是对堆栈上的项目数量设置一个上限,然后说如果你达到这个限制,那么你肯定会处于循环状态并出错。 这样做的缺点当然是没有尽早检测到循环,并且具有更深构建依赖链的包然后限制根本不起作用。

通常更好的选择(因为如果您使用基于堆栈的方法,您可以访问整个堆栈)是简单地遍历堆栈并查看我们尝试安装的项目是否已经在堆栈的任何地方,如果它是出现错误是因为我们遇到了一个循环(这个错误可能会呈现给最终用户,或者最终会冒泡到解析器以尝试不同的版本——尽管这会使它慢得多)。

并直接回答@cjerdonek的问题:原则上这并不难,让事情变得棘手的是一些嵌入式架构假设pip当前的工作方式在每个源构建的世界中不再适用获得自己独立的构建环境,而不是直接在安装环境中运行。

这意味着重用pip的现有依赖管理逻辑而不会绊倒那些内部架构限制并且不冒破坏当前工作代码的风险的最简单方法是在子进程中运行另一个 pip 实例。 这大部分都很好,除了未能检测和摆脱依赖循环可能会导致运行构建的系统分叉炸弹的后果。

我喜欢@dstufft的想法,即转换为迭代/基于堆栈的方法,并使用模式python -c "from pip._internals import coolapithing; coolapithing(sys.stdin.read())"转为内部 pip 函数。 根据讨论,这似乎最简单,而且稳健。

我认为实现这一目标的第一步是将简单的递归方法简化为具有预期输入和输出的单个递归 Python 函数(至少勾画它),然后可以将其转换/转换为迭代方法。 是的,您可以维护set的已访问调用以防止循环,这似乎是更容易解决的方面之一。

我研究/思考了更多关于将递归方法转换为迭代方法的问题。 @xoviat在 PEP 518 (PR #4799) 上的部分工作帮助我找到了递归点(你们中的一些人可能已经熟悉了)。 在他的代码注释中:

# TODO: Use single process with recursion handling

然后它在哪里调用pip install ...

我的想法是,看起来这可能可以通过pip install (用于构建依赖项)的变体来解决,如下所示:

  • 如果安装不需要任何子安装,则进行安装。
  • 否则,返回所需子安装的(可能是部分的)列表(例如,如果写入标准输出不起作用,则将信息写入商定的文件)。

通过这种方式,顶级根进程可以逐步生成构建依赖关系树。 它可以在发现叶子时对其进行处理。 随着叶子的处理,以前不是叶子的节点将成为叶子,依此类推。 通过这种实现,在任何时候,在子进程中最多只会发生一次 pip-install。

与我上面建议的略有不同的是,所需的 pip 命令/子进程调用可以返回/发出候选安装所需的子安装调用列表( pip get-subinstalls或简单的pip subinstalls命令)。 与我上面建议的唯一区别是此命令将仅限于报告信息。 它实际上不会进行安装。 因此实现它可能更简单/更容易测试。

@cjerdonek我认为这个想法没有任何问题。 但最终有人需要实施它(我认为@pradyunsg将在本周末开展一些工作?)并且一如既往地可能会发现更多困难。

有什么东西出现了。 如果其他人想接这个,我没有
问题。 :)

我也喜欢@dstufft的想法。

在 2017 年 10 月 29 日星期日 08:47 xoviat, notifications @github.com 写道:

@cjerdonek https://github.com/cjerdonek我没有看到任何问题
那个想法。 但最终有人需要实现它(我认为
@pradyunsg https://github.com/pradyunsg打算做点什么
这个周末?)和往常一样,可能会发现更多的困难。


你收到这个是因为你被提到了。

直接回复此邮件,在 GitHub 上查看
https://github.com/pypa/pip/issues/4802#issuecomment-340234567或静音
线程
https://github.com/notifications/unsubscribe-auth/ADH7SYImpWgJGg-DzQRcO_9hHfE6ZxEAks5sw-5RgaJpZM4QBdSg
.

回到这一点,我们是否要继续使用@dstufft 建议的堆栈+内部调用方法?

/ping @ncoghlan @pfmoore @xavfernandez

是的,请。 任何事情都可以推动这件事。

有没有人可以总结我们对 PEP 517 和 PEP 518 与 pip 10 版本相关的立场? 具体来说:

  1. master当前是否处于可发布状态? 最后我听说,PEP 518 支持被破坏(至少有一个与 PEP 518 相关的发布阻止程序问题 - #4647)。
  2. 我们是否有可能在某个时间范围内有一个有效的 PEP 517 和/或 PEP 518 实施,使得延迟 pip 10 直到它们可用是合理的?
  3. 假设我们修复了 (1) 中的问题,我们是否要在没有 PEP 517/518 的情况下发布 pip 10 版本? 我们制作了一封有关该版本的提醒电子邮件,因此人们知道它即将到来。 并且其中有一些相当重要的修复(例如,Windows 的编码修复)很适合发布。

我的感觉是我们正在等待发布阻止程序,但我们距离 PEP 517/518 支持还不够近,无法阻止它们上的 pip 10。 但我认为除了作为实施 PEP 518 的一部分外,没有人在处理 #4647。

另一种选择是记录当前 PEP 518 支持的限制,并将 #4647 从发布阻止程序降级。 我对用例了解不多,不知道这是否可行。

我刚刚看到了这个讨论 - 为可能充当分叉炸弹的半生不熟的初始实现道歉,并感谢所有花时间理解它并提出更好想法的人。

FWIW,我认为将其限制为安装轮子以满足构建要求对于第一个版本来说是一个可以接受的折衷方案。

这也提醒我,我可能应该解决问题,以便 flit 本身不是构建要求。

为可能充当分叉炸弹的半生不熟的初始实施道歉,

不需要道歉。 正如我所说,您无法在第一次尝试时预测这些问题。 即使知道我们现在所知道的,推迟 PR 也只会推迟这些讨论。

master当前是否处于可发布状态?

IIUC,它现在可以对系统进行分叉轰炸; 那是对的吗? 如果是这样,我认为不是。

我们是否有可能在某个时间范围内有一个有效的 PEP 517 和/或 PEP 518 实施,使得延迟 pip 10 直到它们可用是合理的?

我认为,简单(短期)的解决方案是只限制轮子来构建依赖项。 我会在下周的某个时候尝试尝试一下。 如果这没有实现,如果我们从 master 中删除当前的 PEP 518 支持并从中删除 10.0.0,我会很好。

除了作为实施 PEP 518 的一部分,我认为没有人在处理 #4647。

我认为您的意思是,PEP 518 的完整实现允许源构建依赖项?

哦,关于#4647—— @xoviat上面的描述说,修复它需要更改/移动代码和对象的所有权/可见性(特别是BuildEnvironment ),这不是微不足道的。

我认为将其限制在轮子上应该像更改此行一样简单:

https://github.com/pypa/pip/blob/fc6b2c192088737f81259b6446f627f20ce46443/src/pip/_internal/wheel.py#L696

到:

finder.format_control = FormatControl(set(), set([':all:']))

第二个字段是一组只能作为二进制文件查找的包, ':all:'的特殊情况表示所有包。

是的。 但仅此一项并不能解决#4647。 此外,这些代码都没有
通过解析器。

2017 年 12 月 2 日星期六 01:23,Thomas Kluyver [email protected]写道:

我认为将它限制在轮子上应该像改变它一样简单
线:

https://github.com/pypa/pip/blob/fc6b2c192088737f81259b6446f627f20ce46443/src/pip/_internal/wheel.py#L696

到:

finder.format_control = FormatControl(set(), set([':all:']))

第二个字段是一组只能作为二进制文件查找的包,其中
':all:' 的特殊情况,表示所有包。


你收到这个是因为你被提到了。

直接回复此邮件,在 GitHub 上查看
https://github.com/pypa/pip/issues/4802#issuecomment-348598368或静音
线程
https://github.com/notifications/unsubscribe-auth/ADH7SUi0QMS3rr5Iba90XWZmFweGmqeBks5s8FlEgaJpZM4QBdSg
.

是的,还有很多其他的问题。 但这应该可以防止它被分叉轰炸,我认为这是最紧迫的问题。

如果有人想接管我原来的 PR(“修复 PEP 518 问题”),
改变它应该不难,这样构建隔离就不会
在没有 pyproject.toml 的情况下启用。 未合并的原始原因
是它放弃了对从源安装依赖项的支持
PEP 518。然而,现在人们开始意识到 PEP 518 可能
根本不在 pip 10 中,他们可能更愿意接受该 PR。 一世
个人没有时间去支持它,但这不应该阻止其他人
从推进它,因为只需要几行更改
(除了 xfailing PEP 518 测试)。

实际上,根据我的更好判断,如果 pip 开发人员同意我的条件,我愿意尽快实施 PEP 517 和 518:

  1. 依赖项最初仅来自轮子
  2. pip 最初会有一个内部构建后端,即使它最终会被删除

我对 1 没有任何问题; 我对 2 没有任何偏好。

在 2017 年 12 月 3 日星期日 02:36 xoviat [email protected]写道:

实际上,根据我更好的判断,我愿意同时实施 PEP
517 和 518 如果 pip 开发人员同意我的条件的话:

  1. 依赖项最初仅来自轮子
  2. pip 最初将有一个内部构建后端,即使它
    最终会被移除


你收到这个是因为你被提到了。

直接回复此邮件,在 GitHub 上查看
https://github.com/pypa/pip/issues/4802#issuecomment-348720096或静音
线程
https://github.com/notifications/unsubscribe-auth/ADH7ST6riptZkYMap5Z5SstRf-VmE7eAks5s8bu5gaJpZM4QBdSg
.

仅供参考,条件不是任意的,但可以使初始实施成为可能。 @pfmoore可以吗?

我对“违背我更好的判断......同意我的条件”的提议的语气不是特别满意。 如果其他 pip 开发人员愿意接受这个提议,我不会反对,但我个人目前没有时间重新开始关于实现细节的整个辩论。 基本上,我会在这方面听从@dstufft@xavfernandez的意见( @pradyunsg已经给出了他的观点)。

报价的基调是因为对于初始实现的外观存在根本分歧,实现方法被关闭。 我宁愿现在就这些原则达成一致,也不愿陷入另一场实施辩论。

我只想说我对这种语气也不是很舒服,这是
只是,我没有时间或精力去解释为什么使用那种语气
等等。我的简短回复的原因相同。

也许还值得一提,我很喜欢仅在二进制文件中构建依赖项
第一次实施,不是长期的。 这不适用于
运行时依赖项(因为这也以某种方式出现在另一个
讨论)。

在 2017 年 12 月 3 日星期日 23:37 xoviat, notifications @github.com 写道:

报价的基调是它的方式,因为方法
由于关于什么的根本分歧,实施被关闭
最初的实现看起来像。 我宁愿同意
原则现在而不是转移到另一场实施辩论中。


你收到这个是因为你被提到了。

直接回复此邮件,在 GitHub 上查看
https://github.com/pypa/pip/issues/4802#issuecomment-348802032或静音
线程
https://github.com/notifications/unsubscribe-auth/ADH7ScUh-BveonoTxZ5FkkeSynFvoLb8ks5s8uNRgaJpZM4QBdSg
.

老实说,这可能不是有效利用任何人的时间来进一步讨论帖子的基调,因为它与在 pip 10 中包含这些功能无关。但是,我需要保证我的条件可以从@pfmoore (谁表示他不能做出这样的保证,这是可以接受的,因为没有人在这里的时间得到报酬)、 @dstufft或 @xavfernandez。

同样,条件不是我个人的意见,而是实施驱动的。 如果我放宽这些条件,那么我就不能保证实现,所以花时间准备 PR 是没有意义的,然后人们阅读差异并问“哦,为什么这条线在这里?” 然后“哦,所以这不是可合并的?” 因为对于 PR 的确切目的存在误解。

同意重新的语气。 我的观点很简单,我不会合并更改[1],所以我的观点在这里并不那么重要。

[1] 显然,我是在说没有看到实现的情况下,所以我希望很清楚我的原因与对代码质量的担忧无关——而是没有时间确保我对代码的理解足够好基本上愿意合并。

@xoviat对于我们上面讨论的迭代与递归方法,您的实施计划是什么?

另外,澄清一下,您是说您将首先完成可以合并的 PEP 517 和 518 的部分实现,然后是可以合并的完整实现? 或者您是说您将只进行部分实现,还是您说您将在不一定可合并的早期阶段进行完整的实现? (我部分地试图更好地理解您在评论中“最初”和“最终”的意思。)

第一个条件消除了整个递归问题。

另外,澄清一下,您是说您将首先完成可以合并的 PEP 517 和 518 的部分实现,然后是可以合并的完整实现?

我的意思是我将完成部分实现,这将适用于 95% 的用例; 特别是在依赖项有轮子的情况下(现在很常见)并且您在 manylinux/windows/OSX 平台上(绝大多数用户)。

这不是一个完整的实现。 但是,您获得不可合并 PR 的方式是尝试采用“全有或全无”的方法,您要么遵守标准,要么不遵守标准。

请记住,完整的实现需要对一些相当讨厌的问题进行分类,每个问题都需要单独的 PR(因为 PR 有 100 多条评论通常意味着代码没有经过很好的审查)。 [1]

[1] https://github.com/btc1/bitcoin/pull/11#issuecomment -313843216

我现在要结束这个问题——我们在 pip 10 中初步支持了 PEP 518,它只支持轮子作为构建依赖项。 我将打开一个新问题来讨论完全支持和另一个关于 PEP 517 支持的问题(在此处引用相关内容)。

感谢@ncoghlan @rgommers @cjerdonek在这里提供的见解和帮助。 感谢@takluyver对 PEP 518 的初始实施。感谢@xoviat (现在是@ghost )在实施这些更改方面提供的所有帮助。 感谢 @benoit-pierre 帮助改进当前的支持。

PS:第 100 条评论! :tada:

该线程已被自动锁定,因为它关闭后没有任何最近的活动。 请为相关错误打开一个新问题。

此页面是否有帮助?
0 / 5 - 0 等级