在`pyproject.toml`中使用环境变量进行版本控制

问题描述 投票:0回答:3

我正在尝试将我的包从

setup.py
迁移到
pyproject.toml
,但我不确定如何以与以前相同的方式进行动态版本控制。目前,当构建用于开发时,我可以使用环境变量传递开发版本。

setup.py
文件看起来与此类似:

import os

from setuptools import setup

import my_package


if __name__ == "__main__":
    dev_version = os.environ.get("DEV_VERSION")
    version = dev_version if dev_version else f"{my_package.__version__}"
    
    setup(
        name="my_package",
        version=version,
        ...
    )

使用

pyproject.toml
文件时有没有办法做类似的事情?

python version setuptools pyproject.toml
3个回答
3
投票

在我写这个答案时,关于如何做到这一点的最真正有效的方法是继续写你的

pyproject.toml
,就像你通常会做的那样,但不是有
version = "..."
字段,而是添加
 dynamic = ["version"]

然后你可以保留一个非常小的

setup.py
文件,它只解析版本的动态值。例如:

# pyproject.toml
[project]
name = "hello-world"
readme = "README.md"
authors = [...]
dependencies = [...]
dynamic = ["version"]

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta:__legacy__"
# The difference between `__legacy__` and the regular `build_meta`
# is that `__legacy__` does the equivalent of
# `sys.path.insert(0, os.path.dirname(__file__))`.
# This allows you to `import` your modules from the `CWD`.
# If you don't like using `__legacy__` you can
# manually add `CWD` to `sys.path` inside your `setup.py`.
# setup.py
import os
from setuptools import setup

import my_package

dev_version = os.environ.get("DEV_VERSION")

setup(
  version=dev_version if dev_version else f"{my_package.__version__}"
)

以下是我对这种方法的评论:

  • Setuptools 允许您将所有静态元数据/配置参数保存在

    pyproject.toml
    中,同时使用逻辑来计算
    setup.py
    中的所有动态部分。 Setuptools 文档明确指出

    通过

    setup()
    提供的元数据和配置是对...
    pyproject.toml
    中存在的信息的补充。

    但是,请务必记住按照

    spec
    编写 dynamic = [...],以允许
    setuptools
    覆盖可通过
    [project]
    表指定的任何值。

  • setup.py
    仅作为可通过
    python setup.py ...
    直接调用的“可运行 CLI 工具”而被弃用。但它仍然是一个完全有效的配置文件,就像
    conftest.py
    pytest
    的有效配置文件,
    noxfile.py
    nox
    的配置文件一样(您通常不调用
    python conftest.py
     python noxfile.py
    ...)。 这方面的证据之一是由 PEP 621 的一位作者撰写的文章 https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html(该文章在
     中建立了 
    [project]
     表) pyproject.toml
    )和
    setuptools
    的维护者。

  • 请注意,我在示例中使用了

    build-backend = "setuptools.build_meta:__legacy__"
    而不是
    build-backend = "setuptools.build_meta"
    。发生这种情况是因为
    __legacy__
    试图模拟运行
    python setup.py ...
    的“副作用”行为,即将
    CWD
    添加到
    sys.path
    。如果您不喜欢这样,您可以在相关导入之前在
    sys.path
    文件中显式操作
    setup.py


1
投票

我想要类似的东西。

不幸的是,toml 不支持环境变量,而且我认为它永远也不想支持。

我尝试了一些自定义构建后端包装器,并筛选了 setuptools(和 setuputils3)层。

我的结论是,没有比编写一个简短的构建脚本来动态编辑 pyproject.toml 文件更简单的解决方案了...

这种事:

#!/bin/bash

#fix version - as toml doesn't support environment vars...
sed -i -e "s/.*version.*/version=\"${DEV_VERSION}\"/g" pyproject.toml

#build python source and binary packages
python3 -m build

对于您的其他情况(非开发),您可以“动态”拉入版本,如其他人在此答案中所述: https://stackoverflow.com/a/74514742/4126317


0
投票

如果您使用 Git,另一种可能值得考虑用于您的用例的替代方案是使用

setuptools_scm
。它使用您的 git 标签来执行动态版本控制。你的 pyproject.toml 看起来像这样:

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

[tool.setuptools_scm]
"version_scheme" = "post-release"
"local_scheme" = "no-local-version"
"write_to" = "mypackage/version.py"

[tool.setuptools.package-dir]
mypackage = "mypackage"

[project]
name = "mypackage"
...
dynamic = ["version"]
© www.soinside.com 2019 - 2024. All rights reserved.