Problems with Python __version__ parsing
As stated by Armin and commenters [*] the change from 0.9 to 0.10 is a convention in open source versioning, and the fault seems to lie more on the version-parsers than the version-suppliers. [†] Armin also notes that the appropriate solution is to use:
from pkg_resources import parse_version
Despite it not being the fault of the version supplier, we've recognized that this can be an issue and can certainly take precautions against letting client code interpret __version__ as a float. Right now there are two ways that I can think of doing this:
Keep __version__ as a tuple. If you keep __version__ in tuple form you don't need to worry about client code forgetting to use the parse_version method.
Use version numbers with more than one decimal. This prohibits the version from being parsed as a float because it's not the correct format — taking the current Linux kernel version as an example:
>>> __version__ = '2.6.26'
>>> float(__version__)
Traceback (most recent call last):
...
ValueError: invalid literal for float(): 2.6.26
>>> tuple(int(i) for i in __version__.split('.'))
(2, 6, 26)
This ensures that the client code will think about a more appropriate way to parse the version number than using the float builtin; however, it doesn't prevent people from performing an inappropriate string comparison like the tuple does.
Footnotes
How not to do software version numbers
There's a really nice, production-ready package called Pygments available from the Cheese Shop. [*] It's a brilliant package, but the developers made a silly mistake. [†]
The release version numbers progress from 0.9 to 0.10.
Sure, this looks reasonable; especially given that in Python developers typically write their version numbers like the following:
>>> import pygments
>>> if pygments.__version__ < (0, 5):
... raise ImportError('Pygments too old.')
...
Traceback (most recent call last):
...
ImportError: Pygments too old.
This would be fine progressing from the (0, 9) tuple to the (0, 10) tuple. However, if your clients interpret your version number as a float (which isn't fully unreasonable, given that it really is represented as a float in writing) and you progress from version 0.9 to 0.10, your code base just fell back 8 minor releases, as in the following:
>>> import pygments
>>> print pygments.__version__
0.10
Additionally, you annoy people like me who get errors like this:
2008-06-17 20:43:58,653 Trac[loader] ERROR: Skipping "TracPygments 0.3dev" ("Pygments>=0.5" not found)
When their setup says this:
cdleary$ pygmentize -V
Pygments version 0.10, (c) 2006-2007 by Georg Brandl .
Anybody who looks at numerical data in a sorted directory is familiar with the results of this phenomenon:
cdleary@gamma:~/example$ ls -l
total 0
-rw-r----- 1 cdleary cdleary 0 2008-06-17 22:00 10
-rw-r----- 1 cdleary cdleary 0 2008-06-17 22:00 11
-rw-r----- 1 cdleary cdleary 0 2008-06-17 22:00 7
-rw-r----- 1 cdleary cdleary 0 2008-06-17 22:00 8
-rw-r----- 1 cdleary cdleary 0 2008-06-17 22:00 9
Which is resolved with a simple prefixing method, as follows:
cdleary@gamma:~/example$ ls -l
total 0
-rw-r----- 1 cdleary cdleary 0 2008-06-17 22:00 07
-rw-r----- 1 cdleary cdleary 0 2008-06-17 22:00 08
-rw-r----- 1 cdleary cdleary 0 2008-06-17 22:00 09
-rw-r----- 1 cdleary cdleary 0 2008-06-17 22:00 10
-rw-r----- 1 cdleary cdleary 0 2008-06-17 22:00 11
Now I have the unfortunate choice of either hacking up my installation to allow the release number, or downgrading.
Footnotes