Commits

Tarek Ziadé  committed dfb7acc

VersionPredicate class is ready

  • Participants
  • Parent commits e1d073e

Comments (0)

Files changed (2)

File src/distutils2/tests/test_version.py

 from distutils2.version import NormalizedVersion as V
 from distutils2.version import IrrationalVersionError
 from distutils2.version import suggest_normalized_version as suggest
+from distutils2.version import VersionPredicate
 
 class VersionTestCase(unittest.TestCase):
 
         # they us "p1" "p2" for post releases
         self.assertEquals(suggest('1.4p1'), '1.4.post1')
 
+    def test_predicate(self):
+        # VersionPredicate knows how to parse stuff like:
+        #
+        #   Project (>=version, ver2)
+
+        predicates = ('zope.interface (>3.5.0)',
+                      'AnotherProject (3.4)',
+                      'OtherProject (<3.0)',
+                      'NoVersion',
+                      'Hey (>=2.5,<2.7)')
+
+        for predicate in predicates:
+            v = VersionPredicate(predicate)
+
+        assert VersionPredicate('Hey (>=2.5,<2.7)').match('2.6')
+        assert VersionPredicate('Ho').match('2.6')
+        assert not VersionPredicate('Hey (>=2.5,!=2.6,<2.7)').match('2.6')
+        assert VersionPredicate('Ho (<3.0)').match('2.6')
+        assert VersionPredicate('Ho (<3.0,!=2.5)').match('2.6.0')
+        assert not VersionPredicate('Ho (<3.0,!=2.6)').match('2.6.0')
+
+
+        # XXX need to silent the micro version in this case
+        #assert not VersionPredicate('Ho (<3.0,!=2.6)').match('2.6.3')
+
 def test_suite():
     #README = os.path.join(os.path.dirname(__file__), 'README.txt')
     #suite = [doctest.DocFileSuite(README), unittest.makeSuite(VersionTestCase)]

File src/distutils2/version.py

 _SPLIT_CMP = re.compile(r"^\s*(<=|>=|<|>|!=|==)\s*([^\s,]+)\s*$")
 
 def _split_predicate(predicate):
-    match = _SPLIT_CMP(predicate)
+    match = _SPLIT_CMP.match(predicate)
     if match is None:
-        raise ValueError('Bad package restriction syntax: %r' % version)
-    comp, version = res.groups()
+        # probably no op, we'll use "=="
+        comp, version = '==', predicate
+    else:
+        comp, version = match.groups()
     return comp, NormalizedVersion(version)
 
 class VersionPredicate(object):
     """Defines a predicate: ProjectName (>ver1,ver2, ..)"""
+
+    _operators = {"<": lambda x, y: x < y,
+                  ">": lambda x, y: x > y,
+                  "<=": lambda x, y: x <= y,
+                  ">=": lambda x, y: x >= y,
+                  "==": lambda x, y: x == y,
+                  "!=": lambda x, y: x != y}
+
     def __init__(self, predicate):
         predicate = predicate.strip()
         match = _PREDICATE.match(predicate)
         if match is None:
             raise ValueError('Bad predicate "%s"' % predicate)
+
         self.name, predicates = match.groups()
         predicates = predicates.strip()
 
+        predicates = _VERSIONS.match(predicates)
         if predicates is not None:
-            predicates = match.groups()[0]
-            self.versions = [_split_predicate(pred)
-                             for pred in predicates.split(',')]
+            predicates = predicates.groups()[0]
+            self.predicates = [_split_predicate(pred.strip())
+                               for pred in predicates.split(',')]
+        else:
+            self.predicates = []
 
+    def match(self, version):
+        """Check if the provided version matches the predicates."""
+        if isinstance(version, str):
+            version = NormalizedVersion(version)
+        for operator, predicate in self.predicates:
+            if not self._operators[operator](version, predicate):
+                return False
+        return True
+