Publishing Releases¶
In this section you will:
Tag a release of your Python package.
Upload it to PyPI (Python Package Index) so that users can download and install it using pip.
We strongly encourage you to share your code GitHub from the start, which is why we covered it in Getting Started. People often overestimate the risks and underestimate the benefits of making their research code public, and the idea of waiting to make it public “until it’s cleaned up” is a punchline, an exercise in infinite regress. But releases are little different: you should wait to publish a release until your package is usable and tested.
Choose a version number. The convention followed by most scientific Python packages is
vMAJOR.MINOR.MICRO
, as inv1.3.0
. A good number to start with isv0.1.0
.These numbers have meanings. The goal is to communicate to the user whether upgrading will break anything in their code that will need to be updated in turn. This is semantic versioning.
Incrementing the
MICRO
number (v1.3.0
->v1.3.1
) means, “I have fixed some bugs, but I have not added any major new features or changed any names. All of your code should still work without changes.”Incrementing the
MINOR
number (v1.3.0
->v1.4.0
) means, “I have added some new features and changed some minor things. Your code should work with perhaps some small updates.”Incrementing the
MAJOR
number (v1.3.0
->v2.0.0
) means, “I have made major changes that will probably require you to update your code.”
Additionally, if the
MAJOR
version is0
, the project is considered to be in early development and may make major breaking changes in minor releases.Obviously this is an imprecise system. Think of it a highly-compressed, lossy representation of how painful it will be for the user to upgrade.
Update
docs/source/release-history.rst
in the documentation if you have not done so already. (See Writing Documentation.) For the first tagged release, you don’t need to write much — some projects just write “Initial release” under the heading with the version and release date. But for every subsequent release, you should list any alterations that could require users of your Python package to change their code. You may also highlight any additions, improvements, and bug fixes. As examples, see the release notes for this small project and this large project.Type
git status
and check that you are on themaster
branch with no uncommitted code.Mark the release with an empty commit, just to leave a marker. This is optional, but it makes it easier to find the release when skimming through the git history.
git commit --allow-empty -m "REL: vX.Y.Z"
Tag the commit.
git tag -a vX.Y.Z # Don't forget the leading v
This will create a tag named
vX.Y.Z
. The-a
flag (strongly recommended) opens up a text editor where you should enter a brief description of the release, such as “This releases fixes some bugs but does not introduce any breaking changes. All users are encouraged to upgrade.”Verify that the
__version__
attribute is correctly updated.The version is reported in three places:
The git tag
The
setup(version=...)
parameter in thesetup.py
fileYour package’s
__version__
attribute, in Python
Versioneer, which was included and configured for you by the cookiecutter template, automatically keeps these three in sync. Just to be sure that it worked properly, start up Python, import the module, and check the
__version__
. It should have automatically updated to match the tag. The leadingv
is not included.import your_package your_package.__version__ # should be 'X.Y.Z'
Incidentally, once you resume development and add the first commit after this tag,
__version__
will take on a value likeX.Y.Z+1.g58ad5f7
, where+1
means “1 commit past version X.Y.Z” and58ad5f7
is the first 7 characters of the hash of the current commit. The letterg
stands for “git”. This is all managed automatically by versioneer and in accordance with the specification in PEP 440.Push the new commit and the tag to
master
.git push origin master git push origin vX.Y.Z
Note
Check your remotes using
git remote -v
. If your respoitory is stored in an organization account, you may need to push toupstream
as well asorigin
.Install wheel, a tool for producing built distributions for PyPI.
python3 -m pip install --upgrade wheel
Remove any extraneous files. If you happen to have any important files in your project directory that are not committed to git, move them first; this will delete them!
git clean -dfx
Publish a release on PyPI. Note that you might need to configure your
~/.pypirc
with a login token. See the packaging documentation for more details.python3 setup.py sdist python3 setup.py bdist_wheel twine upload dist/*
The package is now installable with pip. It may take a couple minutes to become available.
If you would also like to make your package available via conda, we recommend conda-forge, a community-led collection of recipes and build infrastructure. See in particular the section of the conda-forge documentation on adding a recipe.
Finally, if you generally work with an “editable” installation of the package on your machine, as we suggested in Getting Started, you’ll need to reinstall because running
git clean -dfx
above will have wiped out your installation.pip install -e .