Specifying the Version of your Package

Synchronising the version information about your package between, the git repository, the python source code and the python package metadata can be complex.

We strongly recommend using setuptools_scm to do this. With a little effort and understanding it is possible to make the git history the single source of truth for all your version information, for your releases and any development installs.


setuptools_scm is an extension to the setuptools package, which performs two functions:

  • It calculates the version number from the git history.

  • It uses the git repository to get a list of all files to include in the package.

This section is focusing on the first one, the second is discussed in Including data in your package.

setuptools_scm works by calling $ git describe which returns information about the current version of the repository, based on distance away from the last tag on the current branch.

This means that with a little parsing, this information can be used to determine the version of the package at the point where you build packages to release them on PyPI (as described in Releasing Your Package) or when someone accesses my_package.__version__.

When just considering these built packages setuptools_scm works by running git describe at the time you build the package and then saving the output into the code (if configured) and metadata of the package. If you use the default configuration of the template included with this guide, after installing the package the contents of the my_package/_version.py file would be:

# coding: utf-8
# file generated by setuptools_scm
# don't change, don't track in version control
__version__ = version = '0.1.dev0'
__version_tuple__ = version_tuple = (0, 1, 'dev0')

This file is used to provide the __version__ attribute of my_package.

Dynamic Development Versions

The final piece of this puzzle is versions for packages installed in “editable” mode from a git repository. By default when using setuptools_scm when you run pip install -e ./ in your git checkout, it will run git describe and encode the current version into the _version.py file described above. The problem with this approach is that the version number in _version.py will not change, as you make new commits or even add new tags.

The solution to this is to dynamically calculate the version on access of __version__ with setuptools_scm, however, you don’t want to do this for non-development installations as it’s slow and requires setuptools_scm to be installed.

The solution to this implemented in the template (behind an opt-in option) is to make a subpackage called _dev which is not included in the dists (it is excluded in MANIFEST.in) which invokes setuptools. This _dev package is then invoked by the my_pacakge/version.py file, which will fall back to reading the static version from my_package/_version.py file if it can’t access _dev (in the case where it’s not a dev install).