如何为tox项目指定其他tox项目文件夹作为依赖
我们有一个启用了tox的项目(我们称之为“主项目”),它依赖于另一个tox项目(我们称之为“库项目”)——这两个项目都在同一个代码库里,因为它们都是一个大项目的一部分。
普通用户如何使用这个项目
对于普通用户来说,你只需先安装“库”,然后再安装“主项目”,可以直接从代码库或其他来源安装,然后就可以运行了。
我们在tox上遇到的问题
但是,作为开发者,情况就不一样了,因为“tox”应该能够正常工作,而且你可能想同时使用多个版本。
你通常会检出这个大项目的代码库,文件结构大致是这样的:
overarchingproject/main/
overarchingproject/main/src/
overarchingproject/main/tox.ini
overarchingproject/main/setup.py
...
overarchingproject/library/
overarchingproject/library/src/
overarchingproject/library/tox.ini
overarchingproject/library/setup.py
...
现在,如果我进入主项目的文件夹,输入“tox”,会发生以下情况:
当前行为:它会尝试构建“主项目”,并依赖于“库”——这显然会导致它试图从pip获取“库”。但是,这个项目还没有发布(所以在pip上找不到),因此无法正常工作——尽管这个库就在同一个代码库里。
结果是:它不工作。
解决方法1:我们可以建立自己的包索引/让用户这样做。然而,要求每个参与项目的人都使用DevPI或类似工具来运行单元测试似乎不是个好主意,所以我们需要集中处理。
但是,如果我们在某个中心位置提供一个包索引或“库”的pip包,用户就无法轻松运行“主项目”的测试,因为他们可能会使用自己修改过的“库”版本:
毕竟“库”就在同一个代码库里,所以人们可能会在某个时候对它进行修改。
在“主项目”文件夹中输入“tox”并不会轻易找到邻近的“库”版本,而只会找到一个在线的预打包版本,这并不是很直观。
解决方法2:我们尝试了sitepackages=True并在系统中安装“库”——然而,sitepackages=True给我们带来了不少麻烦,通常看起来也不是个好主意。
期望的行为:我们希望tox能够使用同一代码库中“库”的本地版本,这样用户通常可以一次性获取:
这个版本可能是更新的,甚至是本地修改过的,所以这显然是开发者想要使用的。而且这个版本是存在的,而现在pip包就不一定能满足这个要求。
为什么我们要有包含子项目(“主项目”,“库”等)的整体代码库,而不仅仅是一个单一项目?
我们正在开发一个大型的多守护进程项目,包含多个守护进程用于不同的目的,并且有一些共享代码库来构建一个大学课程管理系统(涉及论坛、课程管理、提交作业、学生项目的代码版本控制系统等)。
可以只使用一部分守护进程,所以将它们分开作为不同的项目是有意义的,但它们之间的联系又足够紧密,以至于大多数人会希望同时拥有大部分项目——因此所有项目都在一个代码库中。
这个库本身也适合用于完全不同的项目,但通常我们会首先用它来开发自己的项目——所以它被放在了这个代码库里。这意味着它总是存在于给定的相对路径下,但它有自己独立的tox.ini和单元测试。
总结
那么我们如何让tox在安装项目时查找另一个可用tox项目文件夹中的特定依赖,而不是仅仅依赖pip呢?
当然,“主项目”的常规setup.py安装过程不应该干扰tox或搜索本地磁盘:它只需检查一个特定的相对路径,如果没有找到就放弃(然后回退到pip或其他方式)。
所以最好是能够在tox.ini中以某种方式存储这个相对路径。
或者这一切只是个坏主意?我们是否应该用其他方式来解决这个问题,以便让我们的“主项目”能够轻松使用最新的本地开发版本的“库”,而这个版本就在本地代码库中?
4 个回答
你可以试试其他工具,比如 ansible
。
举个例子:
ansible
可以创建并运行你的虚拟环境。ansible
会安装本地依赖,比如你的子项目。- 在每个子项目中使用
tox
来运行测试、检查代码和生成文档。
这样处理子项目会更方便。
我知道这个问题已经被问了很久,但可能对某些人还是有用。我也尝试过做同样的事情,结果发现可以通过使用 distshare
目录来实现,具体可以参考这个链接:https://tox.wiki/en/latest/example/general.html#access-package-artifacts-between-multiple-tox-runs
# example two/tox.ini [testenv] # install latest package from "one" project deps = {distshare}/one-*.zip
你可以在你的主要项目中使用 pip 的 --editable 选项,像下面这样:
deps =
--editable=file:///{toxinidir}/../library
-r{toxinidir}/requirements.txt
另外,别用这种写法:-e file:///{toxinidir}/../library,因为 tox 会把整个字符串作为参数传给 argparse,结果会出错。
根据对diabloneo的回答的评论建议,可以在tox.ini文件中提供一个install_command
。
我用这个方法写了一个bash脚本,这个脚本可以接受所有常见的pip参数。首先,它会运行pip install --editable="file://`pwd`/../path/to/neighbour/repo"
,然后再执行常规的pip install $@
,这里的$@就是传给脚本的参数(就像tox直接传给pip的一样)。我用这个脚本替代了默认的pip命令,放在install_command
里。
通过这个两步的操作,效果很好 :-)