从git标签中获取版本号(通过pbr)

3
我使用 pbr 进行打包。它从git标签中获取版本并将其应用于setup.py。
现在,我还想在软件包内部提供版本号,例如拥有一个__version__属性。我可以使用pbr库吗?
还有另一个库:versioneer,它也从git标签中提取版本,但这会增加额外的要求。我更喜欢从pbr获得此功能。

“pbr”不已经是一个“额外要求”了吗? - Bailey Parker
这是一个要求,但我无论如何都会用于打包。它从git获取了很多信息,满足DRY原则(作者,ChangeLog等)。它所做的事情之一是生成用于setup.py的版本。只是在寻找一种利用它的方法。 - Roy Prins
3个回答

6

2
考虑使用setuptools_scm,当可用时从git或hg标签中获取版本,或生成适当的开发版本(例如,hgvs-1.2.5.dev6+hb5d989061852.d20181124)。该版本与硬编码版本一样写入包元数据。不需要非标准运行时支持。
虽然我已经在许多项目中使用了setuptools_scm,但我没有使用过PBR。我很好奇并制作了这个简单的演示。
snafu$ head setup.py setup.cfg pbrversiontest/*.py
==> setup.py <==
from setuptools import setup

setup(
    setup_requires=[
        "pbr",
        "setuptools_scm"
    ],
    pbr=True,
    use_scm_version=True,
)

==> setup.cfg <==
[metadata]
name = pbrversiontest
summary = test whether we can use pbr and setuptools_scm

[files]
packages =
    pbrversiontest

==> pbrversiontest/__init__.py <==
# This is straight from setuptools_scm README
from pkg_resources import get_distribution, DistributionNotFound
try:
    __version__ = get_distribution(__name__).version
except DistributionNotFound:
    # package is not installed
    pass

==> pbrversiontest/__main__.py <==
# this isn't required -- only for the demo
import pbrversiontest

print("version is " + pbrversiontest.__version__)

在开发目录中,您可能会有这样的一个会话:
snafu$ python3.6 -mvenv venv/3.6
snafu$ source venv/3.6/bin/activate
(3.6) snafu$ git tag 0.1.2
(3.6) snafu$ pip install -e .
(3.6) snafu$ python -m pbrversiontest 
version is 0.1.2
(3.6) snafu$ pip install wheel
(3.6) snafu$ python setup.py bdist_wheel
...
creating 'dist/pbrversiontest-0.1.2-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it
...
(3.6) snafu$ unzip -l dist/pbrversiontest-0.1.2-py3-none-any.whl 
Archive:  dist/pbrversiontest-0.1.2-py3-none-any.whl
  Length      Date    Time    Name
---------  ---------- -----   ----
      192  2018-11-25 05:26   pbrversiontest/__init__.py
       73  2018-11-25 05:46   pbrversiontest/__main__.py
       33  2018-11-25 06:06   pbrversiontest-0.1.2.dist-info/AUTHORS
      217  2018-11-25 06:06   pbrversiontest-0.1.2.dist-info/METADATA
       92  2018-11-25 06:06   pbrversiontest-0.1.2.dist-info/WHEEL
       47  2018-11-25 06:06   pbrversiontest-0.1.2.dist-info/pbr.json
       15  2018-11-25 06:06   pbrversiontest-0.1.2.dist-info/top_level.txt
      675  2018-11-25 06:06   pbrversiontest-0.1.2.dist-info/RECORD
---------                     -------
     1344                     8 files

这种设置的优点在于,源代码管理工具成为版本标签的唯一/权威来源。这使得代码很难误报其版本号(或prd/dev/rc状态)。 - Reece

1

在正确设置setuptoolspbr之后,有几种方法可以实现:

import pkg_resources  # part of setuptools

# I don't like this one because the version method is hidden
v1 = pkg_resources.require("my_package_name")[0].version
print('v1 {}'.format(v1))

# This is my favorite - the output without .version is just a longer string with
# both the package name, a space, and the version string
v2 = pkg_resources.get_distribution('my_package_name').version
print('v2 {}'.format(v2))

from pbr.version import VersionInfo

# This one seems to be slower, and with pyinstaller makes the exe a lot bigger
v3 = VersionInfo('my_package_name').release_string()
print('v3 {}'.format(v3))

# Update, new option as of Python 3.8 (credit: sinoroc)
# In Python 3.8, importlib.metadata is part of the stdlib,
# which removes run-time dependencies on `pbr` or `setuptools`
import importlib.metadata

__version__ = importlib.metadata.version('my_package_name')

如果您想从命令行获取它,可以执行以下操作:

py setup.py --version

如果软件包始终在本地安装,则甚至可以从脚本中运行setup.py脚本:

from subprocess import Popen, PIPE

(output, err) = Popen('py setup.py --version'.split(' '),
                      stdout=PIPE, stderr=PIPE, text=True).communicate()
if err: print('ERROR: "{}"'.format(err))
else: print('setup.py --version = {}'.format(output))

注意: 有关使用 subprocess 启动和读取 stdout 等的更多详细信息,尤其是在 Python 3.7 之前的旧版本中,请参见 this answer

然后,您可以像这样将 __version__ 添加到您的包 __init__.py 中:

__all__ = (
    '__version__',
    'my_package_name'
)

# Or substitute a different method and assign the result to __version__
import pkg_resources  # part of setuptools

__version__ = pkg_resources.get_distribution("my_package_name").version

以下是一些其他有关设置和如何更新版本等信息的问答,特别是当从您的Git存储库获取信息时(从标签获取版本、作者和ChangeLog信息)可能会有所帮助:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接