=================== 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 :doc:`preliminaries`. 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 in ``v1.3.0``. A good number to start with is ``v0.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 is ``0``, 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 :doc:`writing-docs`.) 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 the ``master`` 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. .. code-block:: bash git commit --allow-empty -m "REL: vX.Y.Z" #. Tag the commit. .. code-block:: bash 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: 1. The git tag 2. The ``setup(version=...)`` parameter in the ``setup.py`` file 3. Your 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 leading ``v`` is not included. .. code-block:: python 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 like ``X.Y.Z+1.g58ad5f7``, where ``+1`` means "1 commit past version X.Y.Z" and ``58ad5f7`` is the first 7 characters of the hash of the current commit. The letter ``g`` 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``. .. code-block:: bash 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 to ``upstream`` as well as ``origin``. #. `Register for a PyPI account `_. #. Install wheel, a tool for producing `built distributions `_ for PyPI. .. code-block:: bash 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! .. code-block:: bash 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. .. code-block:: bash 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 :doc:`preliminaries`, you'll need to reinstall because running ``git clean -dfx`` above will have wiped out your installation. .. code-block:: bash pip install -e .