zoukankan      html  css  js  c++  java
  • 用setuptools_scm来自动控制Python包的版本

    手动管理Python包的版本号一段时间后,寻求自动化的手段,是自然而然的。

    手动管理版本

    手动管理Python包的版本,需要注意两个方面:

    1. 每次发布新包前,要更新包的版本号。
    2. 在安装后的默认模块下应该有一个__version__变量,其值为版本号。

    关于第一点,可以参考《PEP 440 -- Version Identification and Dependency Specification》; 关于第二点,可以参考《PEP 396 -- Module Version Numbers》。 当然,两边的版本号必须是相同的

    除了手动修改两个版本号这种愚蠢的方案以外,要保持两边的版本号一致,无外乎两种方式:

    1. 通过包的版本号来给出__version__的值。
    2. 通过__version__的值来设置包的版本号。

    具体的做法,可以参考《Single-sourcing the package version — Python Packaging User Guide》,其中给出了6种可行方案。 其中也有陷阱,但这里不再详述。 无论如何,这些方案里的版本号总是要手动去改的。

    本文着重介绍其中的第7个方案——setuptools_scm

    自动生成版本号

    setuptools_scm是PYPA推荐的一个自动管理Python包版本号的工具,是setuptools的一个插件。 它会根据包括Git在内的各大VCS的tag,来自动生成一个版本号。

    • 当前commit就在tag上,代码没有修改: {tag}
    • 当前commit就在tag上,代码有修改: {tag}+dYYYMMMDD
    • 当前commit不在tag上,代码没有修改:{next_version}.dev{distance}+{scm letter}{revision hash}
    • 当前commit不在tag上,代码有修改: {next_version}.dev{distance}+{scm letter}{revision hash}.dYYYMMMDD

    使用方式十分简单。 首先,在setup_requires中指定它。 然后,设置use_scm_version。 当然,旧的方式version=*也应该去掉。

    from setuptools import setup
    
    setup(
        ...
        setup_requires=['setuptools_scm'],
        use_scm_version=True,
        # version='0.0.1',  # delete this
        ...
    )
    

    如果Git库的根目录不在setup.py所在的目录,则会出错。 届时,可把use_scm_version替换为以下内容。

        use_scm_version={
            "root": "..",
            "relative_to": __file__,
        },
    

    relative_to是指相对于那里,通常设为setup.py所在目录; root是指定Git库的根目录的相对位置,这里示例的..表示上一级目录,可按需指定。

    设置version

    使用setuptools_scm方案,则版本号是在setup()函数中自动生成的。 主模块的__version__如果需要和它保持一致,就需要读取已安装的当前包的版本号。

    def _get_version(default='x.x.x.dev'):
        try:
            from pkg_resources import DistributionNotFound, get_distribution
        except ImportError:
            return default
        else:
            try:
                return get_distribution(__package__).version
            except DistributionNotFound:  # Run without install
                return default
            except ValueError:  # Python 3 setup
                return default
            except TypeError:  # Python 2 setup
                return default
    
    
    __version__ = _get_version()
    

    以上代码就是孤常用的一个方案。 如果出现任何意外,则返回一个明显错误的版本号x.x.x.dev。 比一般方案更复杂的一点是,孤考虑到了在setup.py中调用这个文件的情况,分别对Python 2.x和3.x做出了处理。

    总结

    setuptools_scm是一个不错的工具,打消了孤自己写一个的念头。 当然它也有一些不如人意的细节,比如next_version的设计。 但瑕不掩瑜,值得一试

  • 相关阅读:
    BZOJ 1907: 树的路径覆盖
    BZOJ 1295: [SCOI2009]最长距离
    BZOJ 1303: [CQOI2009]中位数图
    BZOJ 1468: Tree
    BZOJ 3784: 树上的路径
    BZOJ 2006: [NOI2010]超级钢琴
    BZOJ 1831: [AHOI2008]逆序对
    BZOJ 2521: [Shoi2010]最小生成树
    HDU 6685 Rikka with Coin (枚举 思维)
    HDU 6659 Acesrc and Good Numbers (数学 思维)
  • 原文地址:https://www.cnblogs.com/ExMan/p/10678565.html
Copyright © 2011-2022 走看看