如何共同使用现代Python包装和setuptools插件

308 阅读3分钟

使用现代Python包装的setuptools插件可以进行自动化实验。

Python包装已经有了很大的发展。最新的("beta")使用一个文件,pyproject.toml ,来控制打包。

一个最小的pyproject.toml 可能看起来像这样。

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "cool_project"
version = "1.0.0"

项目部分

项目部分是关于 Python 项目本身的数据,包括像名字版本这样的字段,这些是必须的。

其他字段也经常被使用,包括。

  • description:一个单行的描述。
  • readme:README 文件的位置。
  • 作者:作者姓名和电子邮件。
  • dependencies:这个项目所使用的其他软件包。

构建系统部分

尽管不一定要放在第一位,但构建系统通常放在最前面。这是因为它是最重要的部分。

build-backend键指向一个模块,该模块知道如何从项目中构建源发布和轮子。requires字段允许指定构建时的依赖性。

许多项目是用setuptools构建的。有一些新的替代品,如flithatch

插件

build-system中的requires部分的一个好处是,它可以用来安装插件。尤其是setuptools包,它可以使用插件来修改其行为。

插件可以做的一件事是自动设置版本。这是一个流行的需求,因为版本管理往往是痛苦的。

片断

在继续之前,值得反思一下 "模仿 "的性质。X的模仿X的一个实例,它夸大了某些方面,常常达到幽默的程度。

例如,"间谍电影的模仿 "一部间谍电影,即使它是对这一类型的模仿。

对setuptools插件的戏仿

考虑到这一点,一个模仿setuptools的插件会是什么样子呢?根据上面的规则,它必须是一个插件。

这个名为onedotoh的插件,将版本设置为...为了成为一个插件,它首先必须是一个包。

一个包应该有一个pyproject.toml

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "onedotoh"
version = "1.0.0"

[project.entry-points."setuptools.finalize_distribution_options"]
setuptools_scm = "onedotoh:guess_version"

有一个新的部分:project.entry-points。这意味着函数guess_version将在setuptools准备最终确定发布选项时被调用。

guess_version的代码只有一行。

def guess_version(dist):
    dist.metadata.version = "1.0.0"

版本为1.0.0

使用onedotoh是很微妙的。一个问题是把pyproject.toml 项目部分写成这样。

[project]
name = "a_pyproject"
version = "0.1.2"

pyproject.toml中的版本覆盖插件中的版本。

明显的解决方案是删除版本字段。

[project]
name = "a_pyproject"

这以另一种方式失败了。如果没有项目部分的版本,该文件是无效的。名称将不会被使用。

正确的方法是如下。

[project]
name = "a_pyproject"
dynamic = ["version"]

这种方法明确地将版本字段声明为动态。

一个完整的例子会是这样的。

[build-system]
requires = [
    "setuptools",
    "onedotoh",
]
build-backend = "setuptools.build_meta"

[project]
name = "a_pyproject"
dynamic = ["version"]

最后,版本被自动设置为1.0.0

总结

setuptools插件仍然可以用于现代的Python打包,只要相关的功能被明确声明为 "动态"。这使得一个领域充满了对自动化的进一步实验。