单一采购包版本

有许多技术可以维护项目版本号的单一真实性来源:

  1. 在中读取文件 setup.py 并使用regex解析该版本。示例(来自 pip setup.py ):

    here = os.path.abspath(os.path.dirname(__file__))
    
    def read(*parts):
        with codecs.open(os.path.join(here, *parts), 'r') as fp:
            return fp.read()
    
    def find_version(*file_paths):
        version_file = read(*file_paths)
        version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
                                  version_file, re.M)
        if version_match:
            return version_match.group(1)
        raise RuntimeError("Unable to find version string.")
    
    setup(
       ...
       version=find_version("package", "__init__.py")
       ...
    )
    

    注解

    这种方法的缺点是必须处理正则表达式的复杂性。

  2. 使用一个外部构建工具来管理两个位置的更新,或者提供两个位置都可以使用的API。

    您可以使用的工具很少,没有特定的顺序,也不一定完整: bump2versionchangeszest.releaser .

  3. 将值设置为 __version__ 项目中专用模块中的全局变量(例如 version.py ,然后有 setup.py 阅读和 exec 将值转换为变量。

    version = {}
    with open("...sample/version.py") as fp:
        exec(fp.read(), version)
    # later on we use: version['__version__']
    

    使用此技术的示例: warehouse .

  4. 将值放在一个简单的 VERSION 文本文件和 setup.py 项目代码读取它。

    with open(os.path.join(mypackage_root_dir, 'VERSION')) as version_file:
        version = version_file.read().strip()
    

    这种技术的一个优点是它不特定于Python。任何工具都可以读取版本。

    警告

    通过这种方法,您必须确保 VERSION 文件包含在所有源和二进制分发中(例如,添加 include VERSION 对你 MANIFEST.in

  5. 将值设置为 setup.py 并让项目代码使用 pkg_resources 应用程序编程接口。

    import pkg_resources
    assert pkg_resources.get_distribution('pip').version == '1.2.0'
    

    请注意 pkg_resources API只知道安装元数据中的内容,而不一定是当前导入的代码。

    使用此技术的示例: setuptools .

  6. 将值设置为 __version__ 在里面 sample/__init__.py 和导入 sample 在里面 setup.py .

    import sample
    setup(
        ...
        version=sample.__version__
        ...
    )
    

    警告

    尽管这种技术很常见,但要注意,如果 sample/__init__.py 从导入包 install_requires 依赖项,当 setup.py 运行。

  7. 将版本号保留在版本控制系统(Git、Mercurial等)的标记中而不是代码中,并使用自动从中提取版本号 setuptools_scm .