1 # Check every path through every method of UserDict 2 3 from test import test_support, mapping_tests 4 import UserDict 5 6 d0 = {} 7 d1 = {"one": 1} 8 d2 = {"one": 1, "two": 2} 9 d3 = {"one": 1, "two": 3, "three": 5} 10 d4 = {"one": None, "two": None} 11 d5 = {"one": 1, "two": 1} 12 13 class UserDictTest(mapping_tests.TestHashMappingProtocol): 14 type2test = UserDict.IterableUserDict 15 16 def test_all(self): 17 # Test constructors 18 u = UserDict.UserDict() 19 u0 = UserDict.UserDict(d0) 20 u1 = UserDict.UserDict(d1) 21 u2 = UserDict.IterableUserDict(d2) 22 23 uu = UserDict.UserDict(u) 24 uu0 = UserDict.UserDict(u0) 25 uu1 = UserDict.UserDict(u1) 26 uu2 = UserDict.UserDict(u2) 27 28 # keyword arg constructor 29 self.assertEqual(UserDict.UserDict(one=1, two=2), d2) 30 # item sequence constructor 31 self.assertEqual(UserDict.UserDict([('one',1), ('two',2)]), d2) 32 self.assertEqual(UserDict.UserDict(dict=[('one',1), ('two',2)]), d2) 33 # both together 34 self.assertEqual(UserDict.UserDict([('one',1), ('two',2)], two=3, three=5), d3) 35 36 # alternate constructor 37 self.assertEqual(UserDict.UserDict.fromkeys('one two'.split()), d4) 38 self.assertEqual(UserDict.UserDict().fromkeys('one two'.split()), d4) 39 self.assertEqual(UserDict.UserDict.fromkeys('one two'.split(), 1), d5) 40 self.assertEqual(UserDict.UserDict().fromkeys('one two'.split(), 1), d5) 41 self.assertTrue(u1.fromkeys('one two'.split()) is not u1) 42 self.assertIsInstance(u1.fromkeys('one two'.split()), UserDict.UserDict) 43 self.assertIsInstance(u2.fromkeys('one two'.split()), UserDict.IterableUserDict) 44 45 # Test __repr__ 46 self.assertEqual(str(u0), str(d0)) 47 self.assertEqual(repr(u1), repr(d1)) 48 self.assertEqual(repr(u2), repr(d2)) 49 50 # Test __cmp__ and __len__ 51 all = [d0, d1, d2, u, u0, u1, u2, uu, uu0, uu1, uu2] 52 for a in all: 53 for b in all: 54 self.assertEqual(cmp(a, b), cmp(len(a), len(b))) 55 56 # Test __getitem__ 57 self.assertEqual(u2["one"], 1) 58 self.assertRaises(KeyError, u1.__getitem__, "two") 59 60 # Test __setitem__ 61 u3 = UserDict.UserDict(u2) 62 u3["two"] = 2 63 u3["three"] = 3 64 65 # Test __delitem__ 66 del u3["three"] 67 self.assertRaises(KeyError, u3.__delitem__, "three") 68 69 # Test clear 70 u3.clear() 71 self.assertEqual(u3, {}) 72 73 # Test copy() 74 u2a = u2.copy() 75 self.assertEqual(u2a, u2) 76 u2b = UserDict.UserDict(x=42, y=23) 77 u2c = u2b.copy() # making a copy of a UserDict is special cased 78 self.assertEqual(u2b, u2c) 79 80 class MyUserDict(UserDict.UserDict): 81 def display(self): print self 82 83 m2 = MyUserDict(u2) 84 m2a = m2.copy() 85 self.assertEqual(m2a, m2) 86 87 # SF bug #476616 -- copy() of UserDict subclass shared data 88 m2['foo'] = 'bar' 89 self.assertNotEqual(m2a, m2) 90 91 # Test keys, items, values 92 self.assertEqual(u2.keys(), d2.keys()) 93 self.assertEqual(u2.items(), d2.items()) 94 self.assertEqual(u2.values(), d2.values()) 95 96 # Test has_key and "in". 97 for i in u2.keys(): 98 self.assertIn(i, u2) 99 self.assertEqual(i in u1, i in d1) 100 self.assertEqual(i in u0, i in d0) 101 with test_support.check_py3k_warnings(): 102 self.assertTrue(u2.has_key(i)) 103 self.assertEqual(u1.has_key(i), d1.has_key(i)) 104 self.assertEqual(u0.has_key(i), d0.has_key(i)) 105 106 # Test update 107 t = UserDict.UserDict() 108 t.update(u2) 109 self.assertEqual(t, u2) 110 class Items: 111 def items(self): 112 return (("x", 42), ("y", 23)) 113 t = UserDict.UserDict() 114 t.update(Items()) 115 self.assertEqual(t, {"x": 42, "y": 23}) 116 117 # Test get 118 for i in u2.keys(): 119 self.assertEqual(u2.get(i), u2[i]) 120 self.assertEqual(u1.get(i), d1.get(i)) 121 self.assertEqual(u0.get(i), d0.get(i)) 122 123 # Test "in" iteration. 124 for i in xrange(20): 125 u2[i] = str(i) 126 ikeys = [] 127 for k in u2: 128 ikeys.append(k) 129 keys = u2.keys() 130 self.assertEqual(set(ikeys), set(keys)) 131 132 # Test setdefault 133 t = UserDict.UserDict() 134 self.assertEqual(t.setdefault("x", 42), 42) 135 self.assertTrue(t.has_key("x")) 136 self.assertEqual(t.setdefault("x", 23), 42) 137 138 # Test pop 139 t = UserDict.UserDict(x=42) 140 self.assertEqual(t.pop("x"), 42) 141 self.assertRaises(KeyError, t.pop, "x") 142 self.assertEqual(t.pop("x", 1), 1) 143 t["x"] = 42 144 self.assertEqual(t.pop("x", 1), 42) 145 146 # Test popitem 147 t = UserDict.UserDict(x=42) 148 self.assertEqual(t.popitem(), ("x", 42)) 149 self.assertRaises(KeyError, t.popitem) 150 151 def test_missing(self): 152 # Make sure UserDict doesn't have a __missing__ method 153 self.assertEqual(hasattr(UserDict, "__missing__"), False) 154 # Test several cases: 155 # (D) subclass defines __missing__ method returning a value 156 # (E) subclass defines __missing__ method raising RuntimeError 157 # (F) subclass sets __missing__ instance variable (no effect) 158 # (G) subclass doesn't define __missing__ at a all 159 class D(UserDict.UserDict): 160 def __missing__(self, key): 161 return 42 162 d = D({1: 2, 3: 4}) 163 self.assertEqual(d[1], 2) 164 self.assertEqual(d[3], 4) 165 self.assertNotIn(2, d) 166 self.assertNotIn(2, d.keys()) 167 self.assertEqual(d[2], 42) 168 class E(UserDict.UserDict): 169 def __missing__(self, key): 170 raise RuntimeError(key) 171 e = E() 172 try: 173 e[42] 174 except RuntimeError, err: 175 self.assertEqual(err.args, (42,)) 176 else: 177 self.fail("e[42] didn't raise RuntimeError") 178 class F(UserDict.UserDict): 179 def __init__(self): 180 # An instance variable __missing__ should have no effect 181 self.__missing__ = lambda key: None 182 UserDict.UserDict.__init__(self) 183 f = F() 184 try: 185 f[42] 186 except KeyError, err: 187 self.assertEqual(err.args, (42,)) 188 else: 189 self.fail("f[42] didn't raise KeyError") 190 class G(UserDict.UserDict): 191 pass 192 g = G() 193 try: 194 g[42] 195 except KeyError, err: 196 self.assertEqual(err.args, (42,)) 197 else: 198 self.fail("g[42] didn't raise KeyError") 199 200 ########################## 201 # Test Dict Mixin 202 203 class SeqDict(UserDict.DictMixin): 204 """Dictionary lookalike implemented with lists. 205 206 Used to test and demonstrate DictMixin 207 """ 208 def __init__(self, other=None, **kwargs): 209 self.keylist = [] 210 self.valuelist = [] 211 if other is not None: 212 for (key, value) in other: 213 self[key] = value 214 for (key, value) in kwargs.iteritems(): 215 self[key] = value 216 def __getitem__(self, key): 217 try: 218 i = self.keylist.index(key) 219 except ValueError: 220 raise KeyError 221 return self.valuelist[i] 222 def __setitem__(self, key, value): 223 try: 224 i = self.keylist.index(key) 225 self.valuelist[i] = value 226 except ValueError: 227 self.keylist.append(key) 228 self.valuelist.append(value) 229 def __delitem__(self, key): 230 try: 231 i = self.keylist.index(key) 232 except ValueError: 233 raise KeyError 234 self.keylist.pop(i) 235 self.valuelist.pop(i) 236 def keys(self): 237 return list(self.keylist) 238 def copy(self): 239 d = self.__class__() 240 for key, value in self.iteritems(): 241 d[key] = value 242 return d 243 @classmethod 244 def fromkeys(cls, keys, value=None): 245 d = cls() 246 for key in keys: 247 d[key] = value 248 return d 249 250 class UserDictMixinTest(mapping_tests.TestMappingProtocol): 251 type2test = SeqDict 252 253 def test_all(self): 254 ## Setup test and verify working of the test class 255 256 # check init 257 s = SeqDict() 258 259 # exercise setitem 260 s[10] = 'ten' 261 s[20] = 'twenty' 262 s[30] = 'thirty' 263 264 # exercise delitem 265 del s[20] 266 # check getitem and setitem 267 self.assertEqual(s[10], 'ten') 268 # check keys() and delitem 269 self.assertEqual(s.keys(), [10, 30]) 270 271 ## Now, test the DictMixin methods one by one 272 # has_key 273 self.assertTrue(s.has_key(10)) 274 self.assertTrue(not s.has_key(20)) 275 276 # __contains__ 277 self.assertIn(10, s) 278 self.assertNotIn(20, s) 279 280 # __iter__ 281 self.assertEqual([k for k in s], [10, 30]) 282 283 # __len__ 284 self.assertEqual(len(s), 2) 285 286 # iteritems 287 self.assertEqual(list(s.iteritems()), [(10,'ten'), (30, 'thirty')]) 288 289 # iterkeys 290 self.assertEqual(list(s.iterkeys()), [10, 30]) 291 292 # itervalues 293 self.assertEqual(list(s.itervalues()), ['ten', 'thirty']) 294 295 # values 296 self.assertEqual(s.values(), ['ten', 'thirty']) 297 298 # items 299 self.assertEqual(s.items(), [(10,'ten'), (30, 'thirty')]) 300 301 # get 302 self.assertEqual(s.get(10), 'ten') 303 self.assertEqual(s.get(15,'fifteen'), 'fifteen') 304 self.assertEqual(s.get(15), None) 305 306 # setdefault 307 self.assertEqual(s.setdefault(40, 'forty'), 'forty') 308 self.assertEqual(s.setdefault(10, 'null'), 'ten') 309 del s[40] 310 311 # pop 312 self.assertEqual(s.pop(10), 'ten') 313 self.assertNotIn(10, s) 314 s[10] = 'ten' 315 self.assertEqual(s.pop("x", 1), 1) 316 s["x"] = 42 317 self.assertEqual(s.pop("x", 1), 42) 318 319 # popitem 320 k, v = s.popitem() 321 self.assertNotIn(k, s) 322 s[k] = v 323 324 # clear 325 s.clear() 326 self.assertEqual(len(s), 0) 327 328 # empty popitem 329 self.assertRaises(KeyError, s.popitem) 330 331 # update 332 s.update({10: 'ten', 20:'twenty'}) 333 self.assertEqual(s[10], 'ten') 334 self.assertEqual(s[20], 'twenty') 335 336 # cmp 337 self.assertEqual(s, {10: 'ten', 20:'twenty'}) 338 t = SeqDict() 339 t[20] = 'twenty' 340 t[10] = 'ten' 341 self.assertEqual(s, t) 342 343 def test_main(): 344 test_support.run_unittest( 345 UserDictTest, 346 UserDictMixinTest 347 ) 348 349 if __name__ == "__main__": 350 test_main() 351