Version Type for upgrade comparison (Re: [Zope] Was: Zope
(X)3 FAQ)
Johan Carlsson [EasyPublisher]
johanc@easypublisher.com
Tue, 08 Apr 2003 07:00:38 +0000
At 16:39 2003-04-07 +0200, Lennart Regebro said:
>Johan Carlsson [EasyPublisher] wrote:
>>I think it should use a float instead of a string because it would make it
>>easier to identify the occurrence of an older version than X.X.
>
>Well, that's a good point. Comparing floats is always a pain though, and
>while > and < works, == and != is unrealiable, and you instead have to use
>abs(float - comparefloat) < 0.001 and stuff like that, and for most cases
>all you want to know is if it's the current version or not.
I disagree most cases you want to know if it's never that a specific version.
You may want to reuse the same code to upgrade version 1.6 and 1.7 to
version 1.8.
>Integers would work nice, though.
Yes, integers works nice.
But Oliver tuple examle got me going.
Tuple of integers would be almost perfect, except for:
(2,) != (2,0)
They should evaluate equal.
Also one interesting aspect would be to allow Version to be
constructed from a string, which made me write one.
I have whipped up a little VersionNumber class.
It supports comparisons, addition and subtraction.
It can be initialized from a string or a tuple.
Strings can have any syntax, integers in the string will be
extracted to form a tuple.
Best Regards,
Johan Carlsson
from types import TupleType, ListType
import re
intListRE=re.compile(r'\d+')
class VersionNumber :
def __init__(self, *args):
self.digits=self._parse_args(args)
def _parse_args(self, args):
if len(args)==1:
return tuple(map(lambda x: int(x),intListRE.findall(str(args))))
elif type(args) in (TupleType, ListType):
new_args=()
for arg in args:
try: new_args=new_args+(int(arg),)
except: pass
return new_args
else:
new_args=()
try: new_args=new_args+(int(args),)
except: pass
return new_args
def __repr__(self):
return '.'.join(map(lambda x: str(x), self.digits))
def _normalize(self, others):
selfs=self.digits
if len(selfs)>len(others):
others=others+((0,)*(len(selfs)-len(others)))
elif len(selfs)<len(others):
selfs=selfs+((0,)*(len(others)-len(selfs)))
return selfs, others
def __cmp__(self, other):
if not isinstance(other,self.__class__):
raise TypeError
selfs, others=self._normalize(other.digits)
return cmp(selfs,others)
def __add__(self, other):
if isinstance(other,self.__class__):
others=other.digits
else:
others=self._parse_args(args)
selfs, others=self._normalize(others)
return tuple(map(lambda x,y: x+y, selfs, others))
def __sub__(self, other):
if isinstance(other,self.__class__):
others=other.digits
else:
others=self._parse_args(args)
selfs, others=self._normalize(others)
return tuple(map(lambda x,y: x-y, selfs, others))
#Tests
def compare(e1,e2, value):
result=e1>e2
if result != value:
print "%s > %s\t\t" %(e1,e2),value,result
def is_equal(e1,e2, value):
result=e1==e2
if result != value:
print "%s == %s\t\t" %(e1,e2),value,result
def add(e1,e2, value):
print "%s + %s\t\t" %(e1,e2),e1+e2
def sub(e1,e2, value):
print "%s - %s\t\t" %(e1,e2),e1-e2
def test():
ep16=VersionNumber(1,6)
ep161=VersionNumber(1,6,1)
ep1_6_123=VersionNumber(1,6,123)
ep163=VersionNumber(1,6,3)
ep20=VersionNumber(2,0)
ep2=VersionNumber(2)
print
compare(ep16,ep161, 0)
compare(ep16,ep1_6_123, 0)
compare(ep16,ep16, 0)
compare(ep16,ep20, 0)
compare(ep16,ep163, 0)
compare(ep16,ep2, 0)
compare(ep2,ep20, 0)
compare(ep20,ep161, 1)
print
print "="*25
compare(ep163,ep161, 1)
compare(ep163,ep1_6_123, 0)
compare(ep163,ep16, 1)
compare(ep163,ep20, 0)
compare(ep163,ep163, 0)
compare(ep163,ep2, 0)
compare(ep163,ep20, 0)
compare(ep163,ep161, 1)
print
print "="*25
is_equal(ep163,ep161, 0)
is_equal(ep163,ep1_6_123, 0)
is_equal(ep163,ep16, 0)
is_equal(ep163,ep20, 0)
is_equal(ep163,ep163, 1)
is_equal(ep163,ep2, 0)
is_equal(ep163,ep20, 0)
is_equal(ep163,ep161, 0)
print "-"*25
add(ep163,ep161, 0)
add(ep163,ep1_6_123, 0)
add(ep163,ep16, 0)
add(ep163,ep20, 0)
add(ep163,ep163, 1)
add(ep163,ep2, 0)
add(ep163,ep20, 0)
add(ep163,ep161, 0)
print "-"*25
sub(ep163,ep161, 0)
sub(ep163,ep1_6_123, 0)
sub(ep163,ep16, 0)
sub(ep163,ep20, 0)
sub(ep163,ep163, 1)
sub(ep163,ep2, 0)
sub(ep163,ep20, 0)
sub(ep163,ep161, 0)
print "-"*25
compare(VersionNumber("1,6,3"),VersionNumber("1-6-1"), 1)
compare(VersionNumber("1,6,3"),VersionNumber("1,6,123"), 0)
compare(VersionNumber("1-6-3"),VersionNumber("1.6"), 1)
compare(VersionNumber("1,6,3"),VersionNumber("1.6.,3"), 0)
compare(VersionNumber("1,6,3"),VersionNumber("2"), 0)
compare(VersionNumber("1,6,3"),VersionNumber("2,0"), 0)
compare(VersionNumber("2"),VersionNumber("2-2"), 0)
compare(VersionNumber("ver-2-0"),VersionNumber("1,6,1"), 1)
if __name__ == '__main__':
test()
--
Easy Publisher Developers Team
Johan Carlsson
johanc@easypublisher.com
Mail:
Birkagatan 9
SE-113 36 Stockholm
Sweden
Phone +46-(0)8-31 24 94
Fax +46-(0)8-675 04 44
Mobil +46-(0)70-558 25 24
http://www.easypublisher.com