Pragmatic Python versioning via setuptools and git tags

Some PEP‘s have revolved around the problem of software versioning and dependency tracking.

So, in addition to having some blueprints such as those proposed by the Semantic Versioning guidelines, one needs specifics on how to integrate those practices in our day to day work with version control systems.

Setuptools saves the day by introducing versioning via git tags. In a post by Douglas Creager a strategy to use setuptools with git tags is devised. The workflow for tagging a new version results in:

  1. Tag your release via git tag if the changes are significant.
  2. Run python setup.py install, to bump the version on the filesystem.
  3. git push.

The following code makes it happen:

# Fetch version from git tags, and write to version.py.
# Also, when git is not available (PyPi package), use stored version.py.
version_py = os.path.join(os.path.dirname(__file__), 'version.py')

try:
    version_git = subprocess.check_output(["git", "describe"]).rstrip()
except:
    with open(version_py, 'r') as fh:
        version_git = open(version_py).read().strip().split('=')[-1].replace('"','')

version_msg = "# Do not edit this file, pipeline versioning is governed by git tags"
with open(version_py, 'w') as fh:
    fh.write(version_msg + os.linesep + "__version__=" + version_git)

setup(name="yourpythonpackage",
      version="{ver}".format(ver=version_git),

As an addition to the git tags workflow proposed by Douglas, the ‘__version__’ attribute will be stored in version.py file. This allows the versions to be tracked even when our git repository is not available (i.e, via PyPi package installation), or when such a version needs to be queried from inside your own package.

Thanks Guillermo and Brad for the feedback and suggestions on this strategy.