使用Setuptools(setup.py)构建Python包时使用动态版本

Noa*_*mer 9 python setuptools setup.py sdist

我们有一个大型遗留项目,其中包含一些 python 代码,项目中所有组件的版本都是在运行时由构建项目的构建系统设置的。我们现在需要使用其他组件使用的相同版本来打包 python 代码。
该包当前使用以下命令进行存档,python setup.py bdist_wheel没有版本控制。

问题是我们如何在构建期间将动态版本传递给 setup.py 命令。就像是:

python setup.py --version x.x.x bdist_wheel
Run Code Online (Sandbox Code Playgroud)

有几个选项可以覆盖版本文件,例如version.pyversion.txt使用新版本,然后在文件中使用它setup.py,但假设我们无法向构建过程添加更多步骤,只能修改构建命令和 python 文件,如何才能可以做吗?

其他要求:

  • 如果没有传递任何版本,则应使用默认值。
  • 该版本应该在 python 代码中可用(就像将其作为__version__参数一样__init__.py
  • 如果可能的话应该支持元数据配置的使用setup.cfgpyproject.toml元数据配置

Joh*_*idt 0

如果您选择仅使用setup.py并排除pyproject.tomlsetup.cfg,则可以按照您喜欢的任何方式使用 Python 代码检索包的版本。例如,您可以通过读取脚本EXAMPLE_VERSION中的环境变量(例如 )来获取版本setup.py

import os

import setuptools
from packaging.version import Version

# Try to read version string from env variable
# Default to 0.0.0.dev0 to allow for installs through `pip install -e .`
version_string = os.environ.get("EXAMPLE_VERSION", "0.0.0.dev0")
version = Version(version_string)

setuptools.setup(
    name="package-name",
    version=str(version),
    description="description",
    long_description="long_description",
    install_requires=[],
)
Run Code Online (Sandbox Code Playgroud)

代码来自这个要点

跑步

EXAMPLE_VERSION="0.1.0" python setup.py bdist_wheel
Run Code Online (Sandbox Code Playgroud)

建立分区package_name-0.1.0-py3-none-any.whl

__version__但是,如果您希望模块文件中的变量可以使用该版本__init__.py,则需要在运行脚本时动态更新该变量的值setup.py。这是一个例子:

import os
import re
from pathlib import Path

import setuptools
from packaging.version import Version

init_file = Path(__file__).parent.absolute() / "src/my_module/__init__.py"

# Try to read version string from env variable
# Default to 0.0.0.dev0 to allow for installs through `pip install -e .`
version_string = os.environ.get("EXAMPLE_VERSION", "0.0.0.dev0")
version = Version(version_string)

print(f"### NEW_VERSION: {version} ###")

try:
    # read __init__.py file
    with open(init_file, "r") as f:
        file_contents = f.read()

    # replace __version__ = "0.0.0" string
    new_version_string = f'__version__ = "{version}"'
    new_contents = re.sub(r'^__version__ = ".+"$', new_version_string, file_contents)

    # write content to __init__.py file again
    with open(init_file, "w") as f:
        f.write(new_contents)

    setuptools.setup(
        name="package-name",
        package_dir={"": "src"},
        packages=["my_module"],
        version=str(version),
        description="description",
        long_description="long_description",
        install_requires=[],
    )
finally:
    with open(init_file, "w") as f:
        f.write(file_contents)

Run Code Online (Sandbox Code Playgroud)

跑步

EXAMPLE_VERSION="0.2.0" python setup.py bdist_wheel
Run Code Online (Sandbox Code Playgroud)

将使用版本0.2.0构建bdist_wheel。在此之前,中的变量会被更新。执行命令后,内容被恢复。请注意,我在这里假设一个src布局。__version____init__.pysetuptools.setup__init__.py

我还没有使用pyproject.tomlsetup.cfg配置文件,但限制自己使用setup.py允许您编写执行您想要的操作的代码。