[Checkins] SVN: zope.intid/trunk/ Ensure that the IntId utility never generates ids larger than

Patrick Strawderman patrick at zope.com
Wed Sep 1 17:19:04 EDT 2010


Log message for revision 116108:
  Ensure that the IntId utility never generates ids larger than
  family.maxint, be more careful when accessing volatile attribute.
  

Changed:
  U   zope.intid/trunk/CHANGES.txt
  U   zope.intid/trunk/src/zope/intid/__init__.py
  U   zope.intid/trunk/src/zope/intid/tests.py

-=-
Modified: zope.intid/trunk/CHANGES.txt
===================================================================
--- zope.intid/trunk/CHANGES.txt	2010-09-01 16:40:08 UTC (rev 116107)
+++ zope.intid/trunk/CHANGES.txt	2010-09-01 21:19:04 UTC (rev 116108)
@@ -5,6 +5,8 @@
 3.7.3 (unreleased)
 ------------------
 
+- Bug fix: ensure that the IntId utility never generates ids greater
+  than the maxint of the BTree family being used.
 
 3.7.2 (2009-12-27)
 ------------------

Modified: zope.intid/trunk/src/zope/intid/__init__.py
===================================================================
--- zope.intid/trunk/src/zope/intid/__init__.py	2010-09-01 16:40:08 UTC (rev 116107)
+++ zope.intid/trunk/src/zope/intid/__init__.py	2010-09-01 21:19:04 UTC (rev 116108)
@@ -99,14 +99,18 @@
         same BTree bucket, and randomizes if it stumbles upon a
         used one.
         """
+        nextid = getattr(self, '_v_nextid', None)
         while True:
-            if self._v_nextid is None:
-                self._v_nextid = self._randrange(0, self.family.maxint)
-            uid = self._v_nextid
-            self._v_nextid += 1
+            if nextid is None:
+                nextid = self._randrange(0, self.family.maxint)
+            uid = nextid
             if uid not in self.refs:
+                nextid += 1
+                if nextid > self.family.maxint:
+                    nextid = None
+                self._v_nextid = nextid
                 return uid
-            self._v_nextid = None
+            nextid = None
 
     def register(self, ob):
         # Note that we'll still need to keep this proxy removal.

Modified: zope.intid/trunk/src/zope/intid/tests.py
===================================================================
--- zope.intid/trunk/src/zope/intid/tests.py	2010-09-01 16:40:08 UTC (rev 116107)
+++ zope.intid/trunk/src/zope/intid/tests.py	2010-09-01 21:19:04 UTC (rev 116108)
@@ -13,6 +13,7 @@
 ##############################################################################
 """Tests for the unique id utility.
 """
+import random
 import unittest
 
 import BTrees
@@ -156,18 +157,37 @@
         # This is a somewhat arkward test, that *simulates* the border case
         # behaviour of the _generateId method
         u = self.createIntIds()
-        u._randrange = lambda x,y:int(2**31-1)
+        maxint = u.family.maxint
+        u._randrange = lambda x,y: maxint-1
 
-        # The chosen int is exactly the largest number possible that is
+        conn = ConnectionStub()
+
+        obj = P()
+        conn.add(obj)
+        uid = u.register(obj)
+        self.assertEquals(maxint-1, uid)
+        self.assertEquals(maxint, u._v_nextid)
+
+        # The next chosen int is exactly the largest number possible that is
         # delivered by the randint call in the code
         obj = P()
-        obj._p_jar = ConnectionStub()
+        conn.add(obj)
         uid = u.register(obj)
-        self.assertEquals(2**31-1, uid)
-        # Make an explicit tuple here to avoid implicit type casts on 2**31-1
+        self.assertEquals(maxint, uid)
+        # Make an explicit tuple here to avoid implicit type casts
         # by the btree code
-        self.failUnless(2**31-1 in tuple(u.refs.keys()))
+        self.failUnless(maxint in tuple(u.refs.keys()))
 
+        # _v_nextid is now set to None, since the last id generated was
+        # maxint.
+        self.assertEquals(u._v_nextid, None)
+        # make sure the next uid generated is less than maxint
+        obj = P()
+        conn.add(obj)
+        u._randrange = random.randrange
+        uid = u.register(obj)
+        self.failUnless(uid < maxint)
+
     def test_len_items(self):
         u = self.createIntIds()
         obj = P()



More information about the checkins mailing list