changeset 4956:6638f02fc4b0

added Version class to wikiutil, please use it
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Fri, 21 Aug 2009 23:28:49 +0200
parents 068c47fc2c3a
children fba959635dcd
files MoinMoin/_tests/test_wikiutil.py MoinMoin/wikiutil.py
diffstat 2 files changed, 101 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/_tests/test_wikiutil.py	Sat Aug 15 23:42:41 2009 +0200
+++ b/MoinMoin/_tests/test_wikiutil.py	Fri Aug 21 23:28:49 2009 +0200
@@ -1040,4 +1040,51 @@
                 result = wikiutil.normalize_pagename(test, self.request.cfg)
                 assert result == expected
 
+class TestVersion(object):
+    def test_Version(self):
+        Version = wikiutil.Version
+        # test properties
+        assert Version(1,2,3).major == 1
+        assert Version(1,2,3).minor == 2
+        assert Version(1,2,3).release == 3
+        assert Version(1,2,3,'4.5alpha6').additional == '4.5alpha6'
+        # test Version init and Version to str conversion
+        assert str(Version(1)) == "1.0.0"
+        assert str(Version(1,2)) == "1.2.0"
+        assert str(Version(1,2,3)) == "1.2.3"
+        assert str(Version(1,2,3,'4.5alpha6')) == "1.2.3-4.5alpha6"
+        assert str(Version(version='1.2.3')) == "1.2.3"
+        assert str(Version(version='1.2.3-4.5alpha6')) == "1.2.3-4.5alpha6"
+        # test Version comparison, trivial cases
+        assert Version() == Version()
+        assert Version(1) == Version(1)
+        assert Version(1,2) == Version(1,2)
+        assert Version(1,2,3) == Version(1,2,3)
+        assert Version(1,2,3,'foo') == Version(1,2,3,'foo')
+        assert Version(1) != Version(2)
+        assert Version(1,2) != Version(1,3)
+        assert Version(1,2,3) != Version(1,2,4)
+        assert Version(1,2,3,'foo') != Version(1,2,3,'bar')
+        assert Version(1) < Version(2)
+        assert Version(1,2) < Version(1,3)
+        assert Version(1,2,3) < Version(1,2,4)
+        assert Version(1,2,3,'bar') < Version(1,2,3,'foo')
+        assert Version(2) > Version(1)
+        assert Version(1,3) > Version(1,2)
+        assert Version(1,2,4) > Version(1,2,3)
+        assert Version(1,2,3,'foo') > Version(1,2,3,'bar')
+        # test Version comparison, more delicate cases
+        assert Version(1,12) > Version(1,9)
+        assert Version(1,12) > Version(1,1,2)
+        assert Version(1,0,0,'0.0a2') > Version(1,0,0,'0.0a1')
+        assert Version(1,0,0,'0.0b1') > Version(1,0,0,'0.0a9')
+        assert Version(1,0,0,'0.0b2') > Version(1,0,0,'0.0b1')
+        assert Version(1,0,0,'0.0c1') > Version(1,0,0,'0.0b9')
+        assert Version(1,0,0,'1') > Version(1,0,0,'0.0c9')
+        # test Version playing nice with tuples
+        assert Version(1,2,3) == (1,2,3,'')
+        assert Version(1,2,4) > (1,2,3)
+
+
 coverage_modules = ['MoinMoin.wikiutil']
+
--- a/MoinMoin/wikiutil.py	Sat Aug 15 23:42:41 2009 +0200
+++ b/MoinMoin/wikiutil.py	Fri Aug 21 23:28:49 2009 +0200
@@ -2522,3 +2522,57 @@
 
     return pi, body
 
+
+class Version(tuple):
+    """
+    Version objects store versions like 1.2.3-4.5alpha6 in a structured
+    way and support version comparisons and direct version component access.
+    1: major version (digits only)
+    2: minor version (digits only)
+    3: (maintenance) release version (digits only)
+    4.5alpha6: optional additional version specification (str)
+
+    You can create a Version instance either by giving the components, like:
+        Version(1,2,3,'4.5alpha6')
+    or by giving the composite version string, like:
+        Version(version="1.2.3-4.5alpha6").
+
+    Version subclasses tuple, so comparisons to tuples should work.
+    Also, we inherit all the comparison logic from tuple base class.
+    """
+    VERSION_RE = re.compile(
+        r"""(?P<major>\d+)
+            \.
+            (?P<minor>\d+)
+            \.
+            (?P<release>\d+)
+            (-
+             (?P<additional>.+)
+            )?""",
+            re.VERBOSE)
+
+    @classmethod
+    def parse_version(cls, version):
+        match = cls.VERSION_RE.match(version)
+        if match is None:
+            raise ValueError("Unexpected version string format: %r" % version)
+        v = match.groupdict()
+        return int(v['major']), int(v['minor']), int(v['release']), str(v['additional'] or '')
+
+    def __new__(cls, major=0, minor=0, release=0, additional='', version=None):
+        if version:
+            major, minor, release, additional = cls.parse_version(version)
+        return tuple.__new__(cls, (major, minor, release, additional))
+
+    # properties for easy access of version components
+    major = property(lambda self: self[0])
+    minor = property(lambda self: self[1])
+    release = property(lambda self: self[2])
+    additional = property(lambda self: self[3])
+
+    def __str__(self):
+        version_str = "%d.%d.%d" % (self.major, self.minor, self.release)
+        if self.additional:
+            version_str += "-%s" % self.additional
+        return version_str
+