放弃使用命名空间包

https://blueprints.launchpad.net/oslo-incubator/+spec/drop-namespace-packages

将我们的库安装到命名空间包中导致了几种类型的错误。与其继续与之斗争,我建议我们逐步淘汰它们。

问题描述

setuptools 中的命名空间包支持很脆弱,并且我们在 OpenStack 中常规使用代码的方式会暴露问题,这些问题很难调试。

我们遇到的主要问题是使用不同的安装“模式”将两个独立的库安装到同一个 python 命名空间包中。如果一个库使用 pip install -e 以启用“可编辑”模式安装,而另一个库没有使用 -e 选项作为常规库安装,那么该包的导入路径就会中断,并且一些已安装的组件将无法导入。当 devstack 以可编辑模式安装 Oslo 库时,这种情况经常发生,我们已经更改了 devstack 以默认情况下停止这样做。当开发人员使用系统包安装某些内容,然后从源代码安装另一个库时也会发生这种情况。我们无法真正控制这种行为,因此它仍然会不时出现。

我们还看到在使用配置为允许访问全局 site-packages 目录的 virtualenvs 时出现问题,就像 nova 需要 libvirt 访问权限一样。如果 oslo 命名空间包中的任何内容都全局安装,它将覆盖 virtualenv 中可见的版本。通常情况下,如果全局安装了旧版本,这会导致版本错误,但在这种情况下,它也可能导致导入错误,因为命名空间包不能正确跨越这两个 site-packages 目录。

提议的变更

我建议我们将所有当前的 Oslo 库移出 oslo 命名空间,并创建可以独立导入的简单包。例如,我们将更改

from oslo.foo import bar

变为

from oslo_foo import bar

为了避免与发行版出现问题,我们不应该将 oslo.foo 库重命名为 oslo_foo。这可能会让开发人员感到困惑,因此我们将来可能会重新考虑这个决定,但作为第一步,这不太具侵入性,因为它意味着我们不需要更改我们的需求列表、仓库名称和发行版包名称。

为了支持向后兼容性,我们将为 oslo 命名空间提供 shadow-packages,以便旧的导入形式仍然适用于 Kilo 版本的库。这将给我们时间来更新所有应用程序,并在它们退出长期支持窗口之前,在 M 版本期间完全放弃命名空间包。

迁移到常规包也将允许我们将单元测试移动到库内部,以便它们与 oslo_foo 一起交付和安装,因此我们应该同时进行此操作,仅保留足够的测试套件以确保通过命名空间包公开的公共 API 仍然有效。

现有库的发行名称不会更改,并且将使用相同的模式来创建新库,以避免混淆。这意味着您将 pip install oslo.foo 然后 from oslo_foo import bar

备选方案

  1. lifeless 对 oslo.db 有一个补丁,使用 pkgutils 而不是 setuptools 设置命名空间包

    这保留了使用命名空间包的能力,但代价是运送一个真实的 oslo 库 (https://github.com/rbtcollins/oslo) 并自行维护覆盖代码。不过,我们不知道可能会发现命名空间包的其他问题,因此我更倾向于完全放弃它们。

  2. Python 3 具有更好的原生命名空间包支持,因此当我们将迁移到 Python 3 时,我们可以重新评估此决定。

  3. 什么都不做,并继续帮助开发人员调试其系统上的问题。如果选择此选项,我们可能需要编写一个脚本“why_is_oslo_broken.sh”放入 incubator 中。

“oslo_”名称前缀是用来区分库和非生产库(如 oslotest 和 oslosphinx)的。从理论上讲,我们也可以将它们重命名,以便我们所有的品牌库都具有相同的命名约定。我不知道这是否值得这样做。

Impact on Existing APIs

导入方式会发生变化,但我们不应该需要更改库 API 的其他方面。

安全影响

性能影响

Configuration Impact

开发人员影响

开发人员需要了解导入方式的更改。我们有一些方法可以广泛地传达这些信息

  1. 向 oslo 命名空间包添加弃用警告,以便导入它们会报告警告。

  2. 添加一个 hacking 规则,使导入“from oslo.” 违法。

  3. 依赖审查者来发现它。

选项 1 我们可以自己轻松完成。

选项 2 必须等到我们转换了我们自己的所有库并更新了所有应用程序,但随后可以防止恢复不正确的导入。

选项 3 比较脆弱,所以我不认为我们想仅仅依赖它。

为了方便过渡,我们应该能够准备一个 bash/sed 脚本来对项目进行所需的编辑。我认为我们不会有超过几种不同类型的导入语句,但我们可以根据发现的新模式来更新脚本

Testing Impact

单元测试将在每个库中更新,以便所有测试都针对新的模块名称运行。然后,一些公共 API 测试将被复制,以使用命名空间包,以确保我们不会破坏它。

应用程序中现有的单元测试应该涵盖应用程序中库的使用情况。我们需要更新这些测试中的任何模拟对象。

实现

负责人

主要负责人

Doug Hellmann

其他贡献者

里程碑

完成目标里程碑:K-2(我希望尽早)

工作项

  1. 重新排列我们所有的库代码,包括测试和文档。请参阅 https://review.openstack.org/#/c/127323/ 以获取示例。

  2. 为联络员编写辅助脚本(也许联络员可以执行此操作?)。

孵化

N/A

采用

N/A

N/A

预计 API 稳定

N/A

文档影响

依赖项

参考资料

注意

本作品采用知识共享署名 3.0 非移植许可协议授权。 http://creativecommons.org/licenses/by/3.0/legalcode