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



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

问题是如何在构建时将动态版本传递给setup.py命令。类似于:

python setup.py --version x.x.x bdist_wheel

有几个选项可以用新版本覆盖像version.pyversion.txt这样的版本文件,然后在setup.py文件中使用它,但假设我们不能在构建过程中添加更多步骤,只能修改构建命令和python文件,如何做到这一点?

附加要求:

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

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

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=[],
)

代码来源于此要点。

运行

EXAMPLE_VERSION="0.1.0" python setup.py bdist_wheel

构建distpackage_name-0.1.0-py3-none-any.whl

但是,如果您希望该版本在模块的__init__.py文件中的变量__version__中可用,则在运行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)

运行

EXAMPLE_VERSION="0.2.0" python setup.py bdist_wheel

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

我还没有玩过pyproject.tomlsetup.cfg配置文件,但将自己限制为使用setup.py可以编写您想要的代码。

最新更新