Versioning your Python project for Debian

Version numbers matter! Using a consistent version numbering throughout your project's life matters, too. Changing project name is a high price to pay for cleaning up version errors.

So there's some good news! The Python community's PEP-440 specifies how to use versions.

Here are some examples of versions that abide PEP-440, they are in order!!

  • 0.1.dev1 - Our first release, just playing around. We'll delete it from PyPi.

  • 0.1a1 - After playing around, we decide to release an Alpha 1 for our 0.1 series. We don't know if people might depend on the version, but the Alpha status suggests that the package will be removed from PyPi.

  • 0.1b1 - Then we release a Beta version.

  • 0.1 - Our final release. But of course, more will come.

  • 0.1.post1 - just an hour later, we realize that we forgot a file in and we need to release a new version. PyPi does NOT allow us to overwrite versions so we need to bump the number.

  • 0.1.1 - Following a series of issues or fixes, we release a new update.

  • 0.1.2a1 - The next release contains a couple of fixes that we wanna triage first, so we release an alpha. probably get the picture.

If you are in doubt, you can play around with pkg_resource.parse_version like this:

>>> from pkg_resources import parse_version
>>> parse_version("0.1a1") > parse_version("0.1b1")

Debian compatibility

Debian does not understand "special" characters or words. It just orders by ordinals, letters coming before numbers. You can play around with the rules using this code:

$ if dpkg --compare-versions 0.1a1 lt 0.1; then echo true; else echo false ; fi

Notice that? Debian does not understand the PEP-440 convention. That's because Debian compares 0.1a1 and 0.1 like this: 0=0, 1=1, a>(nothing), 1>(nothing).

In Debian, we should have called it:

$ if dpkg --compare-versions 0.1~a1 lt 0.1; then echo true; else echo false ; fi

This is because ~ orders higher than "nothing".

Maintaining a correct upstream version in Debian?

It's unfortunately not possible to maintain upstream.version~ubuntu1 in case you want to release 0.1a1 followed by0.1.

Debian has introduced "epochs" for fixing wrong or changed versions. However, it will not work to fix our systematic problems. For instance, would you like this?

  • 0:0.1a1

  • 1:0.1

  • 1:0.2a1

  • 2:0.2

Probably not a good idea.

The solution

As stated in the Debian Packaging Policy:

Although this simple approach works most of the times, you may need to adjust package name and upstream version by renaming the upstream source to follow Debian Policy and existing convention.

So with the state of things being that PEP-440 enforces a strict version syntax that's incompatible with a strict Debian version syntax, you should rename your package_VERSION.orig.tar.gz and make sure that VERSION is always translated from your original project's version to Debian's way.

A work flow could look like this:

  1. Bump version number to 0.1a2, release on PyPi

  2. Go to the old debian package source and run uupdate -v 0.1~a2 /path/to/project-0.1a2.tar.gz
  3. Run dch, dpkg-buildpackage -S etc.

So we won't have "pristine upstream version numbers", but we'll get pretty close.