From a48aee11b3ba7636e09d5341e4e6aef6269a7c6d Mon Sep 17 00:00:00 2001
From: david-sarah <david-sarah@jacaranda.org>
Date: Sun, 14 Aug 2011 20:51:53 -0700
Subject: [PATCH] allmydata/__init__.py, test_version.py: make version parsing
 understand '<=', with test. refs #1435

---
 src/allmydata/__init__.py          | 24 +++++++++++++++---------
 src/allmydata/test/test_version.py |  4 ++++
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/src/allmydata/__init__.py b/src/allmydata/__init__.py
index 439fb925..e57b5e62 100644
--- a/src/allmydata/__init__.py
+++ b/src/allmydata/__init__.py
@@ -210,10 +210,10 @@ def get_package_versions_and_locations():
 
 def check_requirement(req, vers_and_locs):
     # TODO: check [] options
-    # We support only disjunctions of >= and ==
+    # We support only disjunctions of <=, >=, and ==
 
     reqlist = req.split(',')
-    name = reqlist[0].split('>=')[0].split('==')[0].strip(' ').split('[')[0]
+    name = reqlist[0].split('<=')[0].split('>=')[0].split('==')[0].strip(' ').split('[')[0]
     if name not in vers_and_locs:
         raise PackagingError("no version info for %s" % (name,))
     if req.strip(' ') == name:
@@ -227,19 +227,25 @@ def check_requirement(req, vers_and_locs):
     actualver = normalized_version(actual, what="actual version %r of %s from %r" % (actual, name, location))
 
     for r in reqlist:
-        s = r.split('>=')
+        s = r.split('<=')
         if len(s) == 2:
             required = s[1].strip(' ')
-            if actualver >= normalized_version(required, what="required minimum version %r in %r" % (required, req)):
-                return  # minimum requirement met
+            if actualver <= normalized_version(required, what="required maximum version %r in %r" % (required, req)):
+                return  # maximum requirement met
         else:
-            s = r.split('==')
+            s = r.split('>=')
             if len(s) == 2:
                 required = s[1].strip(' ')
-                if actualver == normalized_version(required, what="required exact version %r in %r" % (required, req)):
-                    return  # exact requirement met
+                if actualver >= normalized_version(required, what="required minimum version %r in %r" % (required, req)):
+                    return  # minimum requirement met
             else:
-                raise PackagingError("no version info or could not understand requirement %r" % (req,))
+                s = r.split('==')
+                if len(s) == 2:
+                    required = s[1].strip(' ')
+                    if actualver == normalized_version(required, what="required exact version %r in %r" % (required, req)):
+                        return  # exact requirement met
+                else:
+                    raise PackagingError("no version info or could not understand requirement %r" % (req,))
 
     msg = ("We require %s, but could only find version %s.\n" % (req, actual))
     if location and location != 'unknown':
diff --git a/src/allmydata/test/test_version.py b/src/allmydata/test/test_version.py
index 1e7e3e34..836e5965 100644
--- a/src/allmydata/test/test_version.py
+++ b/src/allmydata/test/test_version.py
@@ -13,6 +13,8 @@ class CheckRequirement(unittest.TestCase):
         check_requirement("setuptools >= 0.6c6", {"setuptools": ("0.6", "", "distribute")})
         check_requirement("pycrypto == 2.0.1, == 2.1, >= 2.3", {"pycrypto": ("2.1.0", "", None)})
         check_requirement("pycrypto == 2.0.1, == 2.1, >= 2.3", {"pycrypto": ("2.4.0", "", None)})
+        check_requirement("zope.interface <= 3.6.2, >= 3.6.6", {"zope.interface": ("3.6.1", "", None)})
+        check_requirement("zope.interface <= 3.6.2, >= 3.6.6", {"zope.interface": ("3.6.6", "", None)})
 
         check_requirement("zope.interface", {"zope.interface": ("unknown", "", None)})
         check_requirement("mock", {"mock": ("0.6.0", "", None)})
@@ -30,6 +32,8 @@ class CheckRequirement(unittest.TestCase):
                               "foolscap[secure_connections] >= 0.6.0", {"foolscap": ("0.5.1", "", None)})
         self.failUnlessRaises(PackagingError, check_requirement,
                               "pycrypto == 2.0.1, == 2.1, >= 2.3", {"pycrypto": ("2.2.0", "", None)})
+        self.failUnlessRaises(PackagingError, check_requirement,
+                              "zope.interface <= 3.6.2, >= 3.6.6", {"zope.interface": ("3.6.4", "", None)})
         self.failUnlessRaises(PackagingError, check_requirement,
                               "foo >= 1.0", {})
         self.failUnlessRaises(PackagingError, check_requirement,
-- 
2.45.2