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