I always forgot to get packaging done right on the first try. It is a task that we don't do every day, so I created this how-to gist. It helps out creating packages hosted on GitHUb, listed on PyPi and its documentation hosted on ReadTheDocs.
For the basics, I use to follow this guide, but of course there is plenty of reference documents, tutorials, etc, on the internets.
Make sure you follow version 2.0 of the metadata format using this PEP, otherwise Pip will consider your package as a pre-release:
http://www.python.org/dev/peps/pep-0426/
http://www.pip-installer.org/en/latest/logic.html#pre-release-versions
In your root folder, you must create a docs
folder that will contain the
.rst
files that Sphinx will use to build the documentation necessary for
ReadTheDocs. Following the getting started guide from Read The Docs
is usually enough.
Worth mention is that you can create a separate virtualenv
, install
Sphinx there and use it to build the docs. No need to clutter your
Pip requirements.txt
or any other package management system you use with
an Sphinx dependency!
If you want the statics, templates and docs folders to be included in your
package — along with all the files and subfolders — , do not forget to add the
following lines in your MANIFEST.in
(replace [yourapp]):
recursive-include [yourapp]/static * recursive-include [yourapp]/templates * recursive-include docs *
Note that adding these recursive-includes will add the files and folders to
your distribution package but NOT make setup.py install them. You need to
have package_data
for that (distutils).
In order to create the setup.py
, I copy and edit one of the existing ones
on any of Nomadblue's projects. For example the one from django-nomadlytics
or django-nomad-notifier.
On this file, one of the most important parameters while calling setup()
is to provide a valid URL in the download_url
. This param is constructed
using the __version__
value defined somewhere in our code (note that we
usually do it in the __init__.py
root file of our project).
So for the URL to exist, we must tag our repository with the same name
name as our __version__
returns (e.g. 0.1
), plus prepending a "v"
letter. The tag must be pushed to GitHub, so that the zip release download
URL will be created:
git tag -a v0.1 -m "First version of app" git push --tags git push
Although we have defined a zip file in our GitHub repository as the source for
the package managers (e.g. Pip) to download and install, setuptools
usually
crawls lots of pages looking for any download url that looks like what the
installation needs. This means that if we use upload
as part of our
process, every time we run something like pip install mypackage
, it will
download and use the file uploaded on PyPi and not on Gitub. So we only
register the package on PyPi:
python setup.py register
If we do not care, we can always register our metadate, create a source distribution and upload it with:
python setup.py register sdist upload
It is a good idea to link a webhook between GitHub and ReadTheDocs, so each time we push a new commit with changes on the documentation files ReadTheDocs will build it:
https://docs.readthedocs.org/en/latest/webhooks.html
Do not forget to:
- Update your
CHANGELOG
with the new release changes. - Edit your
docs/conf.py
to updateversion
andrelease
settings (so the documentation title will show the proper release version number) - Go to the Versions admin section of ReadTheDocs to Choose Active Versions for the project.
If you have missed something at this point you may want to re-build, for example, your GitHub release zip file. As the file is generated through the git tag, you can delete and re-create such tag:
git tag -d v0.1 git push origin :refs/tags/v0.1 git tag -a v0.1 -m "First version of app" git push --tags git push
If, while trying to register your app, PyPi answers a 401, check you that your
username and password is properly set on your ~/.pypirc
.