Version Number Comparison Function

K

Keith

Is there a function for comparing version numbers?

E.g.

0.1.0 < 0.1.2
1.876b < 1.876c
3.2.2 < 3.4

Keith
 
C

Christos TZOTZIOY Georgiou

Is there a function for comparing version numbers?

E.g.

0.1.0 < 0.1.2
1.876b < 1.876c
3.2.2 < 3.4

Keith

Convert your version numbers into tuples:

(0, 1, 0) < (0, 1, 2)
(1, 876, 'b') < (1, 876, 'c')
(3, 2, 2) < (3, 4)

All of the above are True.
 
B

Bill Mill

Is there a function for comparing version numbers?

E.g.

0.1.0 < 0.1.2
1.876b < 1.876c
3.2.2 < 3.4

Not by default AFAIK. How about something like (untested):

def test_version(v1, v2):
v1, v2 = v1.split('.'), v2.split('.')
for x, y in zip(v1, v2):
if x < y: return v1
if y > x: return v2

It assumes that v1 and v2 have the same amount of '.'s and that all of
the version numbers are of the same length (i.e. 1.1000 would be <
1.999). How general do you need to be?

Peace
Bill Mill
bill.mill at gmail.com
 
F

Fredrik Lundh

Keith said:
Is there a function for comparing version numbers?

E.g.

0.1.0 < 0.1.2
1.876b < 1.876c
3.2.2 < 3.4

the following works for many common cases:

import re

def cmpver(a, b):
def fixup(i):
try:
return int(i)
except ValueError:
return i
a = map(fixup, re.findall("\d+|\w+", a))
b = map(fixup, re.findall("\d+|\w+", b))
-1

ymmv.

</F>
 
K

Keith

I can't assume there are the same number of '.'s or there are the same
number of digits per version.

I don't know how the tuple comparison works offhand. But that seems
like it would work if you split it.

The suggestion with the "re" module seems generic enough and looks like
it will work as is.

Thanks.
 
D

Dan Sommers

Is there a function for comparing version numbers?
E.g.
0.1.0 < 0.1.2
1.876b < 1.876c
3.2.2 < 3.4

How about a simple string comparison?

Python 2.3.3 (#1, Mar 9 2004, 14:21:31)
[GCC 3.3 20030304 (Apple Computer, Inc. build 1493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
Beyond that, there seems to be sufficient variation between version
number schemes, and something "interesting" often happens immediately
before the final version (e.g. "1.0rc4" becomes "1.0"), that you may
have to know something more about where you particular version numbers
come from.

Regards,
Dan
 
M

Mark Rowe

Is there a function for comparing version numbers?

E.g.

0.1.0 < 0.1.2
1.876b < 1.876c
3.2.2 < 3.4

FWIW,
[LooseVersion ('0.1.0'), LooseVersion ('0.1.2'), LooseVersion
('1.867b'), LooseVersion ('1.867c'), LooseVersion ('3.2.2'),
LooseVersion ('3.4')]
It should be noted that distutils.version provides a StrictVersion
class that offers less flexible but more predictable ordering -- see
the module docstrings for more details.

Regards,

Mark Rowe
<http://bdash.net.nz/>
 
R

Robert Kern

[Pardon the piggybacking. My news-server does not see the OP's message.]

Fredrik said:

distutils has a set of version classes with comparisons.

In [1]:from distutils import version

In [2]:version?
Type: module
Base Class: <type 'module'>
String Form: <module 'distutils.version' from
'/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/distutils/version.pyc'>
Namespace: Interactive
File:
/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/distutils/version.py
Docstring:
Provides classes to represent module version numbers (one class for
each style of version numbering). There are currently two such classes
implemented: StrictVersion and LooseVersion.

Every version number class implements the following interface:
* the 'parse' method takes a string and parses it to some internal
representation; if the string is an invalid version number,
'parse' raises a ValueError exception
* the class constructor takes an optional string argument which,
if supplied, is passed to 'parse'
* __str__ reconstructs the string that was passed to 'parse' (or
an equivalent string -- ie. one that will generate an equivalent
version number instance)
* __repr__ generates Python code to recreate the version number
instance
* __cmp__ compares the current instance with either another instance
of the same class or a string (which will be parsed to an instance
of the same class, thus must follow the same rules)



--
Robert Kern
(e-mail address removed)

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
 
R

Robert Kern

Keith said:
distutils is one of the places I looked:
http://www.python.org/doc/2.3.5/lib/module-distutils.html

But I didn't see the functions documented. I am new to Python so I
didn't know where else to look.

The source! I don't think they're documented elsewhere.
Using distutils seems like it would be the most generic and supported
way to compare version numbers.

Indeed.

--
Robert Kern
(e-mail address removed)

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
 
S

Steve M

I recently saw this:

http://www.egenix.com/files/python/mxTools.html

mx.Tools.verscmp(a,b)
Compares two version strings and returns a cmp() function
compatible value (<,==,> 0). The function is useful for sorting lists
containing version strings.

The logic used is as follows: the strings are compared at each
level, empty levels defaulting to '0', numbers with attached strings
(e.g. '1a1') compare less than numbers without attachement (e.g. '1a1'
< '1).
 
B

Bengt Richter

the following works for many common cases:

import re

def cmpver(a, b):
def fixup(i):
try:
return int(i)
except ValueError:
return i
a = map(fixup, re.findall("\d+|\w+", a))
b = map(fixup, re.findall("\d+|\w+", b))
return cmp(a, b) # -1 if a<b, 0 if a=b, 1 if a>b

[OT] Visually, I like the nested def fixup, and I realize
that for cmpver execution overhead is not likely to be an issue,
but in general, what do you think of not being able
to write it that way if MAKE_FUNCTION overhead is unacceptable?

What if we had something like

@sticky('fixup') # evaluate binding only first time
def cmpver(a , b):
def fixup ... ?

Regards,
Bengt Richter
 
C

Christos TZOTZIOY Georgiou

the following works for many common cases:

import re

def cmpver(a, b):
def fixup(i):
try:
return int(i)
except ValueError:
return i
a = map(fixup, re.findall("\d+|\w+", a))
b = map(fixup, re.findall("\d+|\w+", b))
return cmp(a, b) # -1 if a<b, 0 if a=b, 1 if a>b

[OT] Visually, I like the nested def fixup, and I realize
that for cmpver execution overhead is not likely to be an issue,
but in general, what do you think of not being able
to write it that way if MAKE_FUNCTION overhead is unacceptable?

What if we had something like

@sticky('fixup') # evaluate binding only first time
def cmpver(a , b):
def fixup ... ?

One of the previous related threads is this (long URL):

http://groups-beta.google.com/group...4&mode=thread&noheader=1#doc_7599103bb19c7332
 
E

El Pitonero

Christos said:
One of the previous related threads is this (long URL):
http://groups-beta.google.com/group...4&mode=thread&noheader=1#doc_7599103bb19c7332

Another previous message on this issue:

http://groups-beta.google.com/group/comp.lang.lisp/msg/1615d8b83cca5b20

Python's syntax surely is not clean enough for concise metaprogramming.
At any rate, I'd agree with Fernando's assessment:
The real problem with Python is ... Python is
going the C++ way: piling feature upon feature, adding bells
and whistles while ignoring or damaging its core design.

If the core design were better, many "new features" in Python could
have been rendered unnecessary.
 
B

Bengt Richter

http://groups-beta.google.com/group...4&mode=thread&noheader=1#doc_7599103bb19c7332

Another previous message on this issue:

http://groups-beta.google.com/group/comp.lang.lisp/msg/1615d8b83cca5b20

Python's syntax surely is not clean enough for concise metaprogramming.
At any rate, I'd agree with Fernando's assessment:


If the core design were better, many "new features" in Python could
have been rendered unnecessary.
Do you have specific recommendations that might benefit python 3000?
What better "core design" features would have eliminated what "new features"?
;-)

Regards,
Bengt Richter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top