上下文:
为了能够在 setuptools 中构建时将 GNU gettext po 文件转换为 mo 文件,我创建了一个 setuptools.command.build_py
的子类来编译它们(通过 pymsgfmt 的副本) ) 在调用其基类之前:
from setuptools.command.build_py import build_py as _build_py
class build_py(_build_py):
parent = _build_py
def run(self):
self.compile_po_files() # internal implementation
self.parent.run(self)
def get_outputs(self): # overriden to produce a correct list of installed files
build_mo = self.get_finalized_command("build_mo")
return _build_py.get_outputs(self) + self.outputs
那么我只需在setup
的cmdclass
参数中声明它即可:
setup(
...
cmdclass = {"build_py", mypgk.build_py},
)
到目前为止,一切顺利,当我的模块安装并导入到 setup.py
脚本中时,setuptools 的构建阶段可以正确处理我的 po 文件。
问题:
目标是允许使用 pip 简单地安装源发行版。事情看起来不错,因为 pip 会处理所有在 install_requires
或 setup_requires
参数中声明的依赖项。这就是先有鸡还是先有蛋的问题所在:运行setup.py
时会安装依赖项,但如果不先安装mypkg
,它就无法运行。
当前研究:
我尝试使用神奇的entry_points
在mypkg
setup.py
脚本中声明build_py
覆盖:
...
entry_points = {
"distutils.commands": [
"build_py = mypkg:build_py",
],
}
但它没有任何效果,而我可以这样声明一个有效的新 build_mo
命令:
entry_points = {
"distutils.commands": [
"build_mo = mypkg:build_py",
],
}
长话短说,python setup.py build_mo
调用我的覆盖,而 python setup.py build_py
调用 setuptools 版本。
问题:
为什么我尝试使用 entry_points
声明覆盖 build_py
命令不起作用,我该怎么做?
最佳答案
解释问题
我已经接近解决方案了。经过对 setuptools 文档和源代码的更多研究,我终于意识到它已经使用了entry_points 机制来用自己的命令覆盖distutils 命令。
这意味着当您尝试覆盖 setuptools
命令时,实际上您建议对同一命令进行第二次覆盖。由于 setuptools
处理它的方式,仅使用找到的第一个覆盖,并且根据我的测试,setuptools
是第一个。
我现在可以说,因此,只有来自 distutils
且未在 setuptools
中覆盖的命令才能以这种方式处理。好消息是 build
不会被覆盖,并且在正常使用中,build_py
始终从 build
调用。
可能的解决方案:
由于 build
命令未被 setuptools
覆盖,因此很容易将其替换为 entry_point
。然后,自定义 build
命令类可以更新 cmdclass
目录以声明自定义 build_py
类,因为基 build
会加载它。代码可以是:
from distutils.command.build import build as _build
class build(_build):
parent = _build
def run(self):
self.distribution.cmdclass["build_py"] = build_py
self.parent.run(self)
在我的测试中,让 setuptools
使用自定义 build_py
类就足够了
setup(
...
setup_requires = ["mypkg"],
)
关于python - 如何从 setup_requires 依赖项覆盖 setuptools 命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53478445/