【问题标题】:Get version from git tags (through pbr)从 git 标签获取版本(通过 pbr)
【发布时间】:2018-07-01 05:04:27
【问题描述】:

我使用pbr 进行包装。它从 git 标签中获取版本并将其应用于 setup.py

现在我还想在包中提供可用的版本。例如有一个__version__ 属性。我可以为此使用pbr 库吗?

还有另一个库:versioneer,它也从 git 标签中提取版本,但这会增加一个额外的要求。我更愿意从pbr获得这个功能

【问题讨论】:

  • pbr 不是已经是“额外要求”了吗?
  • 这是一项要求,但无论如何我都会用它来包装。它从 git 中获取大量信息,满足 DRY 原则(作者、ChangeLog 等)。它所做的其中一件事是生成用于 setup.py 的版本。只是在寻找一种利用它的方法。

标签: python versioning


【解决方案1】:

如果您对 pbr 作为包的运行时依赖项感到满意,那么您可以使用来自 pbr.versionVersionInfo 类:

from pbr.version import VersionInfo

package_name='my_package'
info = VersionInfo(package_name)

print(info.version_string())

(另见How to load package version into __version__ variable if you are using pbr?

【讨论】:

    【解决方案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
    

    【讨论】:

    • P.S.像这样设置的优点是 scm 成为版本标签的唯一/权威来源。这使得代码很难歪曲其版本号(或 prd/dev/rc 状态)。
    【解决方案3】:

    正确设置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))
    

    注意:请参阅this answer,了解有关使用子进程启动和读取标准输出等的更多详细信息,尤其是在旧版本的 Python(3.7 之前)上。

    然后您可以像这样将__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 存储库获取信息(来自标签、作者和变更日志信息的版本)时:

    【讨论】:

      猜你喜欢
      • 2013-03-20
      • 2020-02-17
      • 1970-01-01
      • 2013-12-01
      • 1970-01-01
      • 2020-07-17
      • 2018-02-11
      • 2018-12-30
      • 2015-11-02
      相关资源
      最近更新 更多