]>
Commit | Line | Data |
---|---|---|
4710c53d | 1 | """Unit tests for collections.defaultdict."""\r |
2 | \r | |
3 | import os\r | |
4 | import copy\r | |
5 | import tempfile\r | |
6 | import unittest\r | |
7 | from test import test_support\r | |
8 | \r | |
9 | from collections import defaultdict\r | |
10 | \r | |
11 | def foobar():\r | |
12 | return list\r | |
13 | \r | |
14 | class TestDefaultDict(unittest.TestCase):\r | |
15 | \r | |
16 | def test_basic(self):\r | |
17 | d1 = defaultdict()\r | |
18 | self.assertEqual(d1.default_factory, None)\r | |
19 | d1.default_factory = list\r | |
20 | d1[12].append(42)\r | |
21 | self.assertEqual(d1, {12: [42]})\r | |
22 | d1[12].append(24)\r | |
23 | self.assertEqual(d1, {12: [42, 24]})\r | |
24 | d1[13]\r | |
25 | d1[14]\r | |
26 | self.assertEqual(d1, {12: [42, 24], 13: [], 14: []})\r | |
27 | self.assertTrue(d1[12] is not d1[13] is not d1[14])\r | |
28 | d2 = defaultdict(list, foo=1, bar=2)\r | |
29 | self.assertEqual(d2.default_factory, list)\r | |
30 | self.assertEqual(d2, {"foo": 1, "bar": 2})\r | |
31 | self.assertEqual(d2["foo"], 1)\r | |
32 | self.assertEqual(d2["bar"], 2)\r | |
33 | self.assertEqual(d2[42], [])\r | |
34 | self.assertIn("foo", d2)\r | |
35 | self.assertIn("foo", d2.keys())\r | |
36 | self.assertIn("bar", d2)\r | |
37 | self.assertIn("bar", d2.keys())\r | |
38 | self.assertIn(42, d2)\r | |
39 | self.assertIn(42, d2.keys())\r | |
40 | self.assertNotIn(12, d2)\r | |
41 | self.assertNotIn(12, d2.keys())\r | |
42 | d2.default_factory = None\r | |
43 | self.assertEqual(d2.default_factory, None)\r | |
44 | try:\r | |
45 | d2[15]\r | |
46 | except KeyError, err:\r | |
47 | self.assertEqual(err.args, (15,))\r | |
48 | else:\r | |
49 | self.fail("d2[15] didn't raise KeyError")\r | |
50 | self.assertRaises(TypeError, defaultdict, 1)\r | |
51 | \r | |
52 | def test_missing(self):\r | |
53 | d1 = defaultdict()\r | |
54 | self.assertRaises(KeyError, d1.__missing__, 42)\r | |
55 | d1.default_factory = list\r | |
56 | self.assertEqual(d1.__missing__(42), [])\r | |
57 | \r | |
58 | def test_repr(self):\r | |
59 | d1 = defaultdict()\r | |
60 | self.assertEqual(d1.default_factory, None)\r | |
61 | self.assertEqual(repr(d1), "defaultdict(None, {})")\r | |
62 | self.assertEqual(eval(repr(d1)), d1)\r | |
63 | d1[11] = 41\r | |
64 | self.assertEqual(repr(d1), "defaultdict(None, {11: 41})")\r | |
65 | d2 = defaultdict(int)\r | |
66 | self.assertEqual(d2.default_factory, int)\r | |
67 | d2[12] = 42\r | |
68 | self.assertEqual(repr(d2), "defaultdict(<type 'int'>, {12: 42})")\r | |
69 | def foo(): return 43\r | |
70 | d3 = defaultdict(foo)\r | |
71 | self.assertTrue(d3.default_factory is foo)\r | |
72 | d3[13]\r | |
73 | self.assertEqual(repr(d3), "defaultdict(%s, {13: 43})" % repr(foo))\r | |
74 | \r | |
75 | def test_print(self):\r | |
76 | d1 = defaultdict()\r | |
77 | def foo(): return 42\r | |
78 | d2 = defaultdict(foo, {1: 2})\r | |
79 | # NOTE: We can't use tempfile.[Named]TemporaryFile since this\r | |
80 | # code must exercise the tp_print C code, which only gets\r | |
81 | # invoked for *real* files.\r | |
82 | tfn = tempfile.mktemp()\r | |
83 | try:\r | |
84 | f = open(tfn, "w+")\r | |
85 | try:\r | |
86 | print >>f, d1\r | |
87 | print >>f, d2\r | |
88 | f.seek(0)\r | |
89 | self.assertEqual(f.readline(), repr(d1) + "\n")\r | |
90 | self.assertEqual(f.readline(), repr(d2) + "\n")\r | |
91 | finally:\r | |
92 | f.close()\r | |
93 | finally:\r | |
94 | os.remove(tfn)\r | |
95 | \r | |
96 | def test_copy(self):\r | |
97 | d1 = defaultdict()\r | |
98 | d2 = d1.copy()\r | |
99 | self.assertEqual(type(d2), defaultdict)\r | |
100 | self.assertEqual(d2.default_factory, None)\r | |
101 | self.assertEqual(d2, {})\r | |
102 | d1.default_factory = list\r | |
103 | d3 = d1.copy()\r | |
104 | self.assertEqual(type(d3), defaultdict)\r | |
105 | self.assertEqual(d3.default_factory, list)\r | |
106 | self.assertEqual(d3, {})\r | |
107 | d1[42]\r | |
108 | d4 = d1.copy()\r | |
109 | self.assertEqual(type(d4), defaultdict)\r | |
110 | self.assertEqual(d4.default_factory, list)\r | |
111 | self.assertEqual(d4, {42: []})\r | |
112 | d4[12]\r | |
113 | self.assertEqual(d4, {42: [], 12: []})\r | |
114 | \r | |
115 | # Issue 6637: Copy fails for empty default dict\r | |
116 | d = defaultdict()\r | |
117 | d['a'] = 42\r | |
118 | e = d.copy()\r | |
119 | self.assertEqual(e['a'], 42)\r | |
120 | \r | |
121 | def test_shallow_copy(self):\r | |
122 | d1 = defaultdict(foobar, {1: 1})\r | |
123 | d2 = copy.copy(d1)\r | |
124 | self.assertEqual(d2.default_factory, foobar)\r | |
125 | self.assertEqual(d2, d1)\r | |
126 | d1.default_factory = list\r | |
127 | d2 = copy.copy(d1)\r | |
128 | self.assertEqual(d2.default_factory, list)\r | |
129 | self.assertEqual(d2, d1)\r | |
130 | \r | |
131 | def test_deep_copy(self):\r | |
132 | d1 = defaultdict(foobar, {1: [1]})\r | |
133 | d2 = copy.deepcopy(d1)\r | |
134 | self.assertEqual(d2.default_factory, foobar)\r | |
135 | self.assertEqual(d2, d1)\r | |
136 | self.assertTrue(d1[1] is not d2[1])\r | |
137 | d1.default_factory = list\r | |
138 | d2 = copy.deepcopy(d1)\r | |
139 | self.assertEqual(d2.default_factory, list)\r | |
140 | self.assertEqual(d2, d1)\r | |
141 | \r | |
142 | def test_keyerror_without_factory(self):\r | |
143 | d1 = defaultdict()\r | |
144 | try:\r | |
145 | d1[(1,)]\r | |
146 | except KeyError, err:\r | |
147 | self.assertEqual(err.args[0], (1,))\r | |
148 | else:\r | |
149 | self.fail("expected KeyError")\r | |
150 | \r | |
151 | def test_recursive_repr(self):\r | |
152 | # Issue2045: stack overflow when default_factory is a bound method\r | |
153 | class sub(defaultdict):\r | |
154 | def __init__(self):\r | |
155 | self.default_factory = self._factory\r | |
156 | def _factory(self):\r | |
157 | return []\r | |
158 | d = sub()\r | |
159 | self.assertTrue(repr(d).startswith(\r | |
160 | "defaultdict(<bound method sub._factory of defaultdict(..."))\r | |
161 | \r | |
162 | # NOTE: printing a subclass of a builtin type does not call its\r | |
163 | # tp_print slot. So this part is essentially the same test as above.\r | |
164 | tfn = tempfile.mktemp()\r | |
165 | try:\r | |
166 | f = open(tfn, "w+")\r | |
167 | try:\r | |
168 | print >>f, d\r | |
169 | finally:\r | |
170 | f.close()\r | |
171 | finally:\r | |
172 | os.remove(tfn)\r | |
173 | \r | |
174 | \r | |
175 | def test_main():\r | |
176 | test_support.run_unittest(TestDefaultDict)\r | |
177 | \r | |
178 | if __name__ == "__main__":\r | |
179 | test_main()\r |