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