What is the correct way to share package version with setup.py and the package?

后端 未结 7 1772
盖世英雄少女心
盖世英雄少女心 2020-12-07 08:42

With distutils, setuptools, etc. a package version is specified in setup.py:

# file: setup.py
...
setup(
name=\'foobar         


        
7条回答
  •  Happy的楠姐
    2020-12-07 08:58

    I agree with @stefano-m 's philosophy about:

    Having version = "x.y.z" in the source and parsing it within setup.py is definitely the correct solution, IMHO. Much better than (the other way around) relying on run time magic.

    And this answer is derived from @zero-piraeus 's answer. The whole point is "don't use imports in setup.py, instead, read the version from a file".

    I use regex to parse the __version__ so that it does not need to be the last line of a dedicated file at all. In fact, I still put the single-source-of-truth __version__ inside my project's __init__.py.

    Folder heirarchy (relevant files only):

    package_root/
     |- main_package/
     |   `- __init__.py
     `- setup.py
    

    main_package/__init__.py:

    # You can have other dependency if you really need to
    from main_package.some_module import some_function_or_class
    
    # Define your version number in the way you mother told you,
    # which is so straightforward that even your grandma will understand.
    __version__ = "1.2.3"
    
    __all__ = (
        some_function_or_class,
        # ... etc.
    )
    

    setup.py:

    from setuptools import setup
    import re, io
    
    __version__ = re.search(
        r'__version__\s*=\s*[\'"]([^\'"]*)[\'"]',  # It excludes inline comment too
        io.open('main_package/__init__.py', encoding='utf_8_sig').read()
        ).group(1)
    # The beautiful part is, I don't even need to check exceptions here.
    # If something messes up, let the build process fail noisy, BEFORE my release!
    
    setup(
        version=__version__,
        # ... etc.
    )
    

    ... which is still not ideal ... but it works.

    And by the way, at this point you can test your new toy in this way:

    python setup.py --version
    1.2.3
    

    PS: This official Python packaging document (and its mirror) describes more options. Its first option is also using regex. (Depends on the exact regex you use, it may or may not handle quotation marks inside version string. Generally not a big issue though.)

    PPS: The fix in ADAL Python is now backported into this answer.

提交回复
热议问题