summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2003-03-09 07:05:43 (GMT)
committerRaymond Hettinger <python@rcn.com>2003-03-09 07:05:43 (GMT)
commit2c2d322884ee72077a256ec3cd0aa9ce3580eedc (patch)
treed64fac31dcecd48ed44aceb9d5fb6d8dc415e95f
parent42182ebaf6387371c238d2a3484e7f1e085c9d1c (diff)
downloadcpython-2c2d322884ee72077a256ec3cd0aa9ce3580eedc.zip
cpython-2c2d322884ee72077a256ec3cd0aa9ce3580eedc.tar.gz
cpython-2c2d322884ee72077a256ec3cd0aa9ce3580eedc.tar.bz2
SF patch #667730: More DictMixin
* Adds missing pop() methods to weakref.py * Expands test suite to broaden coverage of objects with a mapping interface. Contributed by Sebastien Keim.
-rw-r--r--Lib/test/test_os.py18
-rw-r--r--Lib/test/test_shelve.py49
-rw-r--r--Lib/test/test_userdict.py126
-rw-r--r--Lib/test/test_weakref.py17
-rw-r--r--Lib/weakref.py15
-rw-r--r--Misc/ACKS1
6 files changed, 222 insertions, 4 deletions
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 2b92255..2956d73 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -185,10 +185,28 @@ class StatAttributeTests(unittest.TestCase):
except TypeError:
pass
+from test_userdict import TestMappingProtocol
+
+class EnvironTests(TestMappingProtocol):
+ """check that os.environ object conform to mapping protocol"""
+ _tested_class = None
+ def _reference(self):
+ return {"KEY1":"VALUE1", "KEY2":"VALUE2", "KEY3":"VALUE3"}
+ def _empty_mapping(self):
+ os.environ.clear()
+ return os.environ
+ def setUp(self):
+ self.__save = dict(os.environ)
+ os.environ.clear()
+ def tearDown(self):
+ os.environ.clear()
+ os.environ.update(self.__save)
+
def test_main():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TemporaryFileTests))
suite.addTest(unittest.makeSuite(StatAttributeTests))
+ suite.addTest(unittest.makeSuite(EnvironTests))
run_suite(suite)
if __name__ == "__main__":
diff --git a/Lib/test/test_shelve.py b/Lib/test/test_shelve.py
index e69e311..e7c4b50 100644
--- a/Lib/test/test_shelve.py
+++ b/Lib/test/test_shelve.py
@@ -43,9 +43,54 @@ class TestCase(unittest.TestCase):
self.assertEqual(len(d1), 1)
self.assertNotEqual(d1, d2)
-def test_main():
- test_support.run_unittest(TestCase)
+from test_userdict import TestMappingProtocol
+class TestShelveBase(TestMappingProtocol):
+ fn = "shelftemp.db"
+ counter = 0
+ def __init__(self, *args, **kw):
+ self._db = []
+ TestMappingProtocol.__init__(self, *args, **kw)
+ _tested_class = shelve.Shelf
+ def _reference(self):
+ return {"key1":"value1", "key2":2, "key3":(1,2,3)}
+ def _empty_mapping(self):
+ if self._in_mem:
+ x= shelve.Shelf({}, binary = self._binary)
+ else:
+ self.counter+=1
+ x= shelve.open(self.fn+str(self.counter), binary=self._binary)
+ self._db.append(x)
+ return x
+ def tearDown(self):
+ for db in self._db:
+ db.close()
+ self._db = []
+ if not self._in_mem:
+ for f in glob.glob(self.fn+"*"):
+ os.unlink(f)
+
+class TestAsciiFileShelve(TestShelveBase):
+ _binary = False
+ _in_mem = False
+class TestBinaryFileShelve(TestShelveBase):
+ _binary = True
+ _in_mem = False
+class TestAsciiMemShelve(TestShelveBase):
+ _binary = False
+ _in_mem = True
+class TestBinaryMemShelve(TestShelveBase):
+ _binary = True
+ _in_mem = True
+
+def test_main():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(TestAsciiFileShelve))
+ suite.addTest(unittest.makeSuite(TestBinaryFileShelve))
+ suite.addTest(unittest.makeSuite(TestAsciiMemShelve))
+ suite.addTest(unittest.makeSuite(TestBinaryMemShelve))
+ suite.addTest(unittest.makeSuite(TestCase))
+ test_support.run_suite(suite)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_userdict.py b/Lib/test/test_userdict.py
index cb98308..cbd3bd1 100644
--- a/Lib/test/test_userdict.py
+++ b/Lib/test/test_userdict.py
@@ -4,6 +4,123 @@ import test.test_support, unittest
import UserDict
+class TestMappingProtocol(unittest.TestCase):
+ # This base class can be used to check that an object conforms to the
+ # mapping protocol
+
+ # Functions that can be useful to override to adapt to dictionary
+ # semantics
+ _tested_class = dict # which class is being tested
+
+ def _reference(self):
+ """Return a dictionary of values which are invariant by storage
+ in the object under test."""
+ return {1:2, "key1":"value1", "key2":(1,2,3)}
+ def _empty_mapping(self):
+ """Return an empty mapping object"""
+ return self._tested_class()
+ def _full_mapping(self, data):
+ """Return a mapping object with the value contained in data
+ dictionary"""
+ x = self._empty_mapping()
+ for key, value in data.items():
+ x[key] = value
+ return x
+
+ def __init__(self, *args, **kw):
+ unittest.TestCase.__init__(self, *args, **kw)
+ self.reference = self._reference().copy()
+ key, value = self.reference.popitem()
+ self.other = {key:value}
+
+ def test_read(self):
+ # Test for read only operations on mapping
+ p = self._empty_mapping()
+ p1 = dict(p) #workaround for singleton objects
+ d = self._full_mapping(self.reference)
+ if d is p:
+ p = p1
+ #Indexing
+ for key, value in self.reference.items():
+ self.assertEqual(d[key], value)
+ knownkey = self.other.keys()[0]
+ self.failUnlessRaises(KeyError, lambda:d[knownkey])
+ #len
+ self.assertEqual(len(p), 0)
+ self.assertEqual(len(d), len(self.reference))
+ #has_key
+ for k in self.reference:
+ self.assert_(d.has_key(k))
+ self.assert_(k in d)
+ for k in self.other:
+ self.failIf(d.has_key(k))
+ self.failIf(k in d)
+ #cmp
+ self.assertEqual(cmp(p,p), 0)
+ self.assertEqual(cmp(d,d), 0)
+ self.assertEqual(cmp(p,d), -1)
+ self.assertEqual(cmp(d,p), 1)
+ #__non__zero__
+ if p: self.fail("Empty mapping must compare to False")
+ if not d: self.fail("Full mapping must compare to True")
+ # keys(), items(), iterkeys() ...
+ def check_iterandlist(iter, lst, ref):
+ self.assert_(hasattr(iter, 'next'))
+ self.assert_(hasattr(iter, '__iter__'))
+ x = list(iter)
+ x.sort()
+ lst.sort()
+ ref.sort()
+ self.assert_(x==lst==ref)
+ check_iterandlist(d.iterkeys(), d.keys(), self.reference.keys())
+ check_iterandlist(iter(d), d.keys(), self.reference.keys())
+ check_iterandlist(d.itervalues(), d.values(), self.reference.values())
+ check_iterandlist(d.iteritems(), d.items(), self.reference.items())
+ #get
+ key, value = d.iteritems().next()
+ knownkey, knownvalue = self.other.iteritems().next()
+ self.assertEqual(d.get(key, knownvalue), value)
+ self.assertEqual(d.get(knownkey, knownvalue), knownvalue)
+ self.failIf(knownkey in d)
+
+ def test_write(self):
+ # Test for write operations on mapping
+ p = self._empty_mapping()
+ #Indexing
+ for key, value in self.reference.items():
+ p[key] = value
+ self.assertEqual(p[key], value)
+ for key in self.reference.keys():
+ del p[key]
+ self.failUnlessRaises(KeyError, lambda:p[key])
+ p = self._empty_mapping()
+ #update
+ p.update(self.reference)
+ self.assertEqual(dict(p), self.reference)
+ d = self._full_mapping(self.reference)
+ #setdefaullt
+ key, value = d.iteritems().next()
+ knownkey, knownvalue = self.other.iteritems().next()
+ self.assertEqual(d.setdefault(key, knownvalue), value)
+ self.assertEqual(d[key], value)
+ self.assertEqual(d.setdefault(knownkey, knownvalue), knownvalue)
+ self.assertEqual(d[knownkey], knownvalue)
+ #pop
+ self.assertEqual(d.pop(knownkey), knownvalue)
+ self.failIf(knownkey in d)
+ self.assertRaises(KeyError, d.pop, knownkey)
+ default = 909
+ d[knownkey] = knownvalue
+ self.assertEqual(d.pop(knownkey, default), knownvalue)
+ self.failIf(knownkey in d)
+ self.assertEqual(d.pop(knownkey, default), default)
+ #popitem
+ key, value = d.popitem()
+ self.failIf(key in d)
+ self.assertEqual(value, self.reference[key])
+ p=self._empty_mapping()
+ self.assertRaises(KeyError, p.popitem)
+
d0 = {}
d1 = {"one": 1}
d2 = {"one": 1, "two": 2}
@@ -11,7 +128,9 @@ d3 = {"one": 1, "two": 3, "three": 5}
d4 = {"one": None, "two": None}
d5 = {"one": 1, "two": 1}
-class UserDictTest(unittest.TestCase):
+class UserDictTest(TestMappingProtocol):
+ _tested_class = UserDict.IterableUserDict
+
def test_all(self):
# Test constructors
u = UserDict.UserDict()
@@ -182,7 +301,9 @@ class SeqDict(UserDict.DictMixin):
def keys(self):
return list(self.keylist)
-class UserDictMixinTest(unittest.TestCase):
+class UserDictMixinTest(TestMappingProtocol):
+ _tested_class = SeqDict
+
def test_all(self):
## Setup test and verify working of the test class
@@ -275,6 +396,7 @@ class UserDictMixinTest(unittest.TestCase):
def test_main():
suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(TestMappingProtocol))
suite.addTest(unittest.makeSuite(UserDictTest))
suite.addTest(unittest.makeSuite(UserDictMixinTest))
test.test_support.run_suite(suite)
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
index 3a548cd..b078b17 100644
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -517,11 +517,28 @@ class MappingTestCase(TestBase):
self.assert_(len(d) == 1)
self.assert_(d.items() == [('something else', o2)])
+from test_userdict import TestMappingProtocol
+
+class WeakValueDictionaryTestCase(TestMappingProtocol):
+ """Check that WeakValueDictionary class conforms to the mapping protocol"""
+ __ref = {"key1":Object(1), "key2":Object(2), "key3":Object(3)}
+ _tested_class = weakref.WeakValueDictionary
+ def _reference(self):
+ return self.__ref.copy()
+
+class WeakKeyDictionaryTestCase(TestMappingProtocol):
+ """Check that WeakKeyDictionary class conforms to the mapping protocol"""
+ __ref = {Object("key1"):1, Object("key2"):2, Object("key3"):3}
+ _tested_class = weakref.WeakKeyDictionary
+ def _reference(self):
+ return self.__ref.copy()
def test_main():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(ReferencesTestCase))
suite.addTest(unittest.makeSuite(MappingTestCase))
+ suite.addTest(unittest.makeSuite(WeakValueDictionaryTestCase))
+ suite.addTest(unittest.makeSuite(WeakKeyDictionaryTestCase))
test_support.run_suite(suite)
diff --git a/Lib/weakref.py b/Lib/weakref.py
index 6153bd9..838ff5e 100644
--- a/Lib/weakref.py
+++ b/Lib/weakref.py
@@ -101,6 +101,18 @@ class WeakValueDictionary(UserDict.UserDict):
if o is not None:
return key, o
+ def pop(self, key, *args):
+ try:
+ o = self.data.pop(key)()
+ except KeyError:
+ if args:
+ return args[0]
+ raise
+ if o is None:
+ raise KeyError, key
+ else:
+ return o
+
def setdefault(self, key, default):
try:
wr = self.data[key]
@@ -225,6 +237,9 @@ class WeakKeyDictionary(UserDict.UserDict):
if o is not None:
return o, value
+ def pop(self, key, *args):
+ return self.data.pop(ref(key), *args)
+
def setdefault(self, key, default):
return self.data.setdefault(ref(key, self._remove),default)
diff --git a/Misc/ACKS b/Misc/ACKS
index f4ecd10..abc1c75 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -281,6 +281,7 @@ Bob Kahn
Tamito Kajiyama
Jacob Kaplan-Moss
Lou Kates
+Sebastien Keim
Randall Kern
Robert Kern
Magnus Kessler