Search code examples
pythonversioning

Get version from git tags (through pbr)


I use pbr for packaging. It takes the version from git tags and applies that to setup.py

Now I also want to have the version available inside the package. For instance to have a __version__ attribute. Can I use the pbr library for this?

There is another library: versioneer that also extracts the version from the git tags, but that would add an extra requirement. I would prefer to get this functionality from pbr


Solution

  • After properly setting up for setuptools and pbr, here are several ways to do it:

    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')
    

    If you want it from the command line, you can do:

    py setup.py --version
    

    Or even run the setup.py script from within a script, if the package will always be installed locally:

    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))
    

    Note: See this answer for more details on using subprocess to launch and read stdout, etc., especially on older versions of Python (prior to 3.7).

    You can then add __version__ to your package __init__.py like this:

    __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
    

    Some other Q&A that might help with setup and details on how to update the version and other info, especially if getting info from your Git repo (version from tags, Authors, and ChangeLog info):