BASIC EDIT: The old answer was too hectic. Here are two more beautiful solutions.
So, currently, I see three ways to achieve the desired order, frees up candidates "rc" to the actual releases.
- my old, imperative style
- use "b" instead of "rc" to use
StrictVersion , from the same package - extend the
Version class to add support for custom tags and tag organizing
1. Old, imperative style
from distutils.version import LooseVersion versions = ["1.7.0", "1.7.0.rc0", "1.8.0"] lv = [LooseVersion(v) for v in versions] lv.sort() sorted_rc = [v.vstring for v in lv] import re p = re.compile('rc\\d+$') i = 0
with this i get:
['1.7.0rc0', '1.7.0', '1.11.0']
2. Use "b" instead of "rc"
The distutils.version package also has another StrictVersion class that does the job if your 1.7.0.rc0 can be written as 1.7.0a0 or 1.7.0b0 , marking alpha or beta releases.
I.e:
from distutils.version import StrictVersion versions = ["1.7.0", "1.7.0b0", "1.11.0"] sorted(versions, key=StrictVersion)
This gives:
['1.7.0b0', '1.7.0', '1.11.0']
Translation from one form to another can be done using the re module.
3. Extend the version class
An obvious problem with the previous solution is the lack of StrictVersion flexibility. By changing the attribute of the version_re class to use rc instead of a or b , even if it takes 1.7.1rc0 , it still prints it as 1.7.1r0 (starting with python 2.7.3).
We can fix this by implementing our own custom version class. This can be done as follows: with some unit tests to ensure correctness, at least in some cases:
#!/usr/bin/python
Thus, it can be used as follows:
import version2 versions = ["1.7.0", "1.7.0rc2", "1.7.0rc1", "1.7.1", "1.11.0"] sorted(versions, key=lambda v: version2.NumberedVersion(v, '.', ['rc']))
exit:
['1.7.0rc1', '1.7.0rc2', '1.7.0', '1.7.1', '1.11.0']
So in conclusion, use the batteries included in python, or deploy your own.
About this implementation: it could be improved by turning to trailing zeros in releases, and memoize compiling regular expressions.