python - 如何从 setup_requires 依赖项覆盖 setuptools 命令?

标签 python overriding setuptools

上下文:

为了能够在 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

那么我只需在setupcmdclass参数中声明它即可:

setup(
    ...
    cmdclass = {"build_py", mypgk.build_py},
)

到目前为止,一切顺利,当我的模块安装并导入到 setup.py 脚本中时,setuptools 的构建阶段可以正确处理我的 po 文件。

问题:

目标是允许使用 pip 简单地安装源发行版。事情看起来不错,因为 pip 会处理所有在 install_requiressetup_requires 参数中声明的依赖项。这就是先有鸡还是先有蛋的问题所在:运行setup.py时会安装依赖项,但如果不先安装mypkg,它就无法运行。

当前研究:

我尝试使用神奇的entry_pointsmypkgsetup.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/

相关文章:

Python - 创建一个运行代码的 EXE,而不是编译时的代码

java - 如何重写方法

python - 如何从源代码中使用 package_data 中的数据?

setuptools - 从 python bdist_egg 或 bdist_wheel 中排除单个源文件

python - setuptools 在安装过程中发现错误的包

java - 如何在 Java 或 Python 中使用文件系统缓存?

python - 如何请求多个页面而不等待输出?

CSS 规则覆盖 :not

c++ - 强制转换是可覆盖的操作吗?如果是这样,如何?

python - 有条件合并列表中的子列表