跳转到主要内容

基于VCS的项目版本字符串管理

项目描述

Versioneer

这是一个用于管理基于setuptools的Python项目中记录的版本号的工具。目标是消除发布流程中繁琐且容易出错的“更新嵌入式版本字符串”步骤。发布新版本应该和记录版本控制系统中的新标签一样简单,也许还需要制作新的tarball。

快速安装

Versioneer提供了两种安装模式。经典的 vendored 模式将versioneer的一个副本安装到你的仓库中。实验性的构建时依赖模式旨在允许你跳过此步骤并简化升级过程。

Vendored 模式

  • pip install versioneer 安装到你的$PATH中的某个位置
    • 有可用的conda-forge配方,因此你也可以使用conda install -c conda-forge versioneer
  • [tool.versioneer]部分添加到你的pyproject.toml中,或将[versioneer]部分添加到你的setup.cfg中(参见安装
    • 注意,如果你使用pyproject.toml,你需要将tomli; python_version < "3.11"添加到你的构建时依赖中
  • 在你的源树中运行versioneer install --vendor,提交结果
  • 使用python setup.py version验证版本信息

构建时依赖模式

  • pip install versioneer 安装到你的$PATH中的某个位置
    • 有可用的conda-forge配方,因此你也可以使用conda install -c conda-forge versioneer
  • [tool.versioneer]部分添加到你的pyproject.toml中,或将[versioneer]部分添加到你的setup.cfg中(参见安装
  • versioneer(如果配置在pyproject.toml中,则带有[toml]额外部分)添加到pyproject.tomlbuild-system表的requires键中
    [build-system]
    requires = ["setuptools", "versioneer[toml]"]
    build-backend = "setuptools.build_meta"
    
  • 在你的源树中运行versioneer install --no-vendor,提交结果
  • 使用python setup.py version验证版本信息

版本标识符

源树来自各种地方

  • 版本控制系统的检出(主要用于开发者)
  • 由构建自动化产生的夜间tarball
  • 由基于Web的VCS浏览器(如github的“标签tarball”功能)产生的快照tarball
  • 由“setup.py sdist”产生的发布tarball,通过PyPI分发

在每个源树内部,版本标识符(可以是字符串或数字,此工具不关心格式)可以来自各种地方

  • 询问VCS工具本身,例如“git describe”(用于检出),该工具了解最近的“标签”和绝对修订号
  • 解包tarball的目录名称
  • 展开的VCS关键字($Id$等)
  • 由某些早期构建步骤创建的_version.py

对于已发布的软件,版本标识符与VCS标签密切相关。有些项目使用包含不仅仅是版本字符串的标签名称(例如,“myproject-1.2”而不是只是“1.2”),在这种情况下,工具需要删除标签前缀以提取版本标识符。对于未发布的软件(在标签之间),版本标识符应提供足够的信息以帮助开发者重建相同的树,同时让他们了解树的大致年龄(在版本1.2之后,在版本1.3之前)。许多VCS系统可以报告描述这一点的信息,例如,git describe --tags --dirty --always报告类似于“0.7-1-g574ab98-dirty”的信息,表示检出是0.7标签之后的一个修订,有一个唯一的修订号“574ab98”,并且是“dirty”(它有未提交的更改)。

版本标识符用于多个目的

  • 允许模块自我标识其版本:myproject.__version__
  • 为“setup.py sdist” tarball选择名称和前缀

工作原理

Versioneer通过在源树中添加一个特殊的_version.py文件来工作,其中你的__init__.py可以导入它。这个_version.py知道如何在导入时动态地从VCS工具获取版本信息。

_version.py还包含$Revision$标记,安装过程将_version.py标记为在git archive命令期间用标签名称重写此标记。因此,生成的tarballs将包含足够的信息来获取正确的版本。

为了允许setup.py也计算版本,我们在源树的最顶层添加了versioneer.py,它紧挨着setup.py和配置它的setup.cfg。这覆盖了几个distutils/setuptools命令,在调用时计算版本,并将setup.py buildsetup.py sdist改为用包含生成版本数据的小静态文件替换_version.py

安装

有关详细安装说明,请参阅INSTALL.md

版本字符串类型

使用Versioneer的代码可以通过从主__init__.py文件导入_version并在其中运行get_versions()函数来在运行时了解其版本字符串。从“外部”(例如在setup.py中),您可以导入顶级versioneer.py并运行get_versions()

这两个函数都返回一个包含不同版本信息类型的字典

  • ['version']:使用所选样式渲染的简短版本字符串。这是项目版本字符串最常用的值。默认的“pep440”样式产生如0.110.11+2.g1076c970.11+2.g1076c97.dirty之类的字符串。有关替代样式的信息,请参阅下方的“样式”部分。

  • ['full-revisionid']:详细的修订标识符。对于Git,这是完整的SHA1提交ID,例如“1076c978a8d3cfc70f408fe5974aa6c092c949ac”。

  • ['date']:最新HEAD提交的日期和时间。对于Git,它是ISO 8601格式的提交日期。如果没有日期,这将是None。

  • ['dirty']:布尔值,如果树中有未提交的更改,则为True。请注意,只有在这些更改是在VCS签出中运行的时,这个值才是准确的,否则它可能是False或None。

  • ['error']:如果无法计算版本字符串,这将设置为描述问题的字符串,否则将为None。如果在setup.py中设置此值,可能会抛出异常,以避免例如创建版本字符串为“未知”的tarball。

某些变体比其他变体更有用。在错误报告中包括full-revisionid应允许开发者重建正在测试的确切代码(或指示应该与开发者共享的本地更改)。version适用于在“关于”框或CLI --version输出中显示:它可以轻松地与发布说明和各个版本中修复的错误列表进行比较。

安装程序会将以下文本添加到您的__init__.py中,以便在YOURPROJECT.__version__中放置一个基本版本

from ._version import get_versions
__version__ = get_versions()['version']
del get_versions

样式

setup.cfg中的style=配置控制如何将VCS信息渲染到版本字符串中。

默认样式“pep440”产生一个PEP440兼容的字符串,等于实际发布的不带前缀的标签名称,并包含一个附加的“本地版本”部分,其中包含更多中间构建的详细信息。对于Git,这是TAG[+DISTANCE.gHEX[.dirty]],使用git describe --tags --dirty --always的信息。例如,“0.11+2.g1076c97.dirty”表示树类似于“1076c97”提交,但具有未提交的更改(“.dirty”),并且此提交比“0.11”标签两个修订版。对于已发布的软件(与已知标签完全相等),标识符将仅包含清除的标签,例如“0.11”。

其他样式可用。有关描述,请参阅Versioneer源树中的details.md

调试

Versioneer试图避免致命错误:如果出现问题,它往往会返回版本为“0+unknown”。要调查问题,请运行setup.py version,这将以详细模式运行版本查找代码,并显示get_versions()的完整内容(包括可能有助于识别错误的error字符串)。

已知限制

一些已知情况会导致Versioneer版本控制出现问题。以下列出了其中最重要的几个。更多详情可以在Github 问题页面找到。

子项目

Versioneer对那些setup.py不在根目录的源树(例如,setup.py.git/不是兄弟)支持有限。以下有两种常见原因导致setup.py不在根目录:

  • 包含多个子项目的源树,例如Buildbot,其中包含“master”和“slave”子项目,每个子项目都有自己的setup.pysetup.cfgtox.ini。这类项目会生成多个PyPI发行版(并上传多个独立安装的tar包)。
  • 以包含C库为主要目的,但也在子目录中提供Python(以及其他语言)绑定的源树。

Versioneer会在父目录中查找.git,并且大多数操作应该得到正确的版本字符串。然而,pipsetuptools存在bug和实现细节,这通常会导致从子项目目录执行pip install .时无法找到正确的版本字符串(所以它通常默认为0+unknown)。

pip install --editable .应该能正常工作。有时setup.py install也可能工作。

已知Pip-8.1.1存在此问题,但希望它会在后续版本中得到修复。

问题#38正在跟踪此问题。在PR#61的讨论中,从Versioneer的角度更详细地描述了该问题。pip PR#3176pip PR#3615包含了改进pip以使Versioneer正确工作的代码。

Versioneer-0.16及更早版本只会在setup.cfg旁边查找.git目录,所以这些版本中完全不支持子项目。

setuptools <= 18.5的编辑安装

setup.py developpip install --editable .允许您将项目安装到一个虚拟环境中一次,然后继续编辑源代码(和测试),而无需在每次更改后重新安装。

“入口脚本”(setup(entry_points={"console_scripts": ..}))是指定应与Python包一起安装的可执行脚本的一种方便方式。

这两种方式在使用现代setuptools时按预期工作。然而,在使用setuptools-18.5或更早版本时,某些操作在运行入口脚本时会导致pkg_resources.DistributionNotFound错误,这需要通过重新安装包来解决问题。这发生在安装使用一个版本进行,然后在检出不同版本时重新生成egg_info数据。许多setup.py命令会导致egg_info重建(包括sdistwheel和安装到不同的虚拟环境中),所以这可能会令人惊讶。

问题#83描述了这个问题,但升级到较新的setuptools版本可能解决它。

更新Versioneer

要将您的项目升级到Versioneer的新版本,请执行以下操作:

  • 安装新的Versioneer(pip install -U versioneer或等效命令)
  • 如有必要,编辑setup.cfgpyproject.toml,以包括发布说明中指示的任何新配置设置。有关详细信息,请参阅UPGRADING
  • 在您的源树中重新运行versioneer install --[no-]vendor,以替换SRC/_version.py
  • 提交所有更改的文件

未来方向

该工具旨在使其易于扩展到其他版本控制系统:所有特定于版本控制系统的组件都位于单独的目录中,如src/git/。顶层的versioneer.py脚本通过运行make-versioneer.py来组装这些组件。在未来,make-versioneer.py将接受VCS名称作为参数,并构建一个针对特定VCS的versioneer.py版本。它也可能接受在安装期间通过编辑setup.py手动提供的配置参数。或者,它也可能朝相反的方向发展,包括所有受支持的VCS系统的代码,减少中间脚本的数目。

类似的项目

许可证

为了使Versioneer更容易嵌入,其所有代码都归入公共领域。它创建的_version.py也位于公共领域。具体来说,两者都根据https://unlicense.org/中描述的“Unlicense”发布。

项目详情


下载文件

下载适用于您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源代码分发

versioneer-0.29.tar.gz (75.1 kB 查看散列)

上传时间 源代码

构建分发

versioneer-0.29-py3-none-any.whl (46.8 kB 查看散列)

上传时间 Python 3

支持者

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面