blob: 86b47ded4d3b58a64b249e0f80c8c31df59492bb [file] [log] [blame]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001"""Unit tests for collections.py."""
2
Guido van Rossumd8faa362007-04-27 19:54:29 +00003import unittest
4from test import test_support
Guido van Rossum8ce8a782007-11-01 19:42:39 +00005from collections import namedtuple
Guido van Rossumcd16bf62007-06-13 18:07:49 +00006from collections import Hashable, Iterable, Iterator
7from collections import Sized, Container, Callable
8from collections import Set, MutableSet
9from collections import Mapping, MutableMapping
10from collections import Sequence, MutableSequence
11
Guido van Rossumd8faa362007-04-27 19:54:29 +000012
13class TestNamedTuple(unittest.TestCase):
14
15 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +000016 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +000017 self.assertEqual(Point.__name__, 'Point')
18 self.assertEqual(Point.__doc__, 'Point(x, y)')
19 self.assertEqual(Point.__slots__, ())
20 self.assertEqual(Point.__module__, __name__)
21 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Guido van Rossum8ce8a782007-11-01 19:42:39 +000022
23 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
24 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
25 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
26
27 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
28 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
29 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
30 self.assertRaises(ValueError, namedtuple, 'abc', '__efg__ ghi') # field with double underscores
31 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
32
33 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Guido van Rossumd8faa362007-04-27 19:54:29 +000034
35 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +000036 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +000037 p = Point(11, 22)
38 self.assertEqual(p, Point(x=11, y=22))
39 self.assertEqual(p, Point(11, y=22))
40 self.assertEqual(p, Point(y=22, x=11))
41 self.assertEqual(p, Point(*(11, 22)))
42 self.assertEqual(p, Point(**dict(x=11, y=22)))
43 self.assertRaises(TypeError, Point, 1) # too few args
44 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
45 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
46 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
47 self.assertEqual(repr(p), 'Point(x=11, y=22)')
48 self.assert_('__dict__' not in dir(p)) # verify instance has no dict
49 self.assert_('__weakref__' not in dir(p))
Thomas Wouters1b7f8912007-09-19 03:06:30 +000050 self.assertEqual(p.__fields__, ('x', 'y')) # test __fields__ attribute
51 self.assertEqual(p.__replace__('x', 1), (1, 22)) # test __replace__ method
Guido van Rossum8ce8a782007-11-01 19:42:39 +000052 self.assertEqual(p.__asdict__(), dict(x=11, y=22)) # test __dict__ method
Thomas Wouters1b7f8912007-09-19 03:06:30 +000053
54 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +000055 Point = namedtuple('Point', 'x, y')
56 p = Point(x=11, y=22)
57 self.assertEqual(repr(p), 'Point(x=11, y=22)')
58
59 # verify that fieldspec can be a non-string sequence
60 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +000061 p = Point(x=11, y=22)
62 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +000063
64 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +000065 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +000066 p = Point(11, 22)
67
68 self.assert_(isinstance(p, tuple))
69 self.assertEqual(p, (11, 22)) # matches a real tuple
70 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
71 self.assertEqual(list(p), [11, 22]) # coercable to a list
72 self.assertEqual(max(p), 22) # iterable
73 self.assertEqual(max(*p), 22) # star-able
74 x, y = p
75 self.assertEqual(p, (x, y)) # unpacks like a tuple
76 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
77 self.assertRaises(IndexError, p.__getitem__, 3)
78
79 self.assertEqual(p.x, x)
80 self.assertEqual(p.y, y)
81 self.assertRaises(AttributeError, eval, 'p.z', locals())
82
Thomas Wouters1b7f8912007-09-19 03:06:30 +000083 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +000084 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +000085 self.assertEqual(Zero(), ())
Guido van Rossum8ce8a782007-11-01 19:42:39 +000086 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +000087 self.assertEqual(Dot(1), (1,))
88
Guido van Rossumd8faa362007-04-27 19:54:29 +000089
Guido van Rossumcd16bf62007-06-13 18:07:49 +000090class TestOneTrickPonyABCs(unittest.TestCase):
91
92 def test_Hashable(self):
93 # Check some non-hashables
Guido van Rossum98297ee2007-11-06 21:34:58 +000094 non_samples = [buffer(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +000095 for x in non_samples:
96 self.failIf(isinstance(x, Hashable), repr(x))
97 self.failIf(issubclass(type(x), Hashable), repr(type(x)))
98 # Check some hashables
99 samples = [None,
100 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000101 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000102 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000103 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000104 ]
105 for x in samples:
106 self.failUnless(isinstance(x, Hashable), repr(x))
107 self.failUnless(issubclass(type(x), Hashable), repr(type(x)))
108 self.assertRaises(TypeError, Hashable)
109 # Check direct subclassing
110 class H(Hashable):
111 def __hash__(self):
112 return super().__hash__()
113 self.assertEqual(hash(H()), 0)
114 self.failIf(issubclass(int, H))
115
116 def test_Iterable(self):
117 # Check some non-iterables
118 non_samples = [None, 42, 3.14, 1j]
119 for x in non_samples:
120 self.failIf(isinstance(x, Iterable), repr(x))
121 self.failIf(issubclass(type(x), Iterable), repr(type(x)))
122 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000123 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000124 tuple(), list(), set(), frozenset(), dict(),
125 dict().keys(), dict().items(), dict().values(),
126 (lambda: (yield))(),
127 (x for x in []),
128 ]
129 for x in samples:
130 self.failUnless(isinstance(x, Iterable), repr(x))
131 self.failUnless(issubclass(type(x), Iterable), repr(type(x)))
132 # Check direct subclassing
133 class I(Iterable):
134 def __iter__(self):
135 return super().__iter__()
136 self.assertEqual(list(I()), [])
137 self.failIf(issubclass(str, I))
138
139 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +0000140 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000141 for x in non_samples:
142 self.failIf(isinstance(x, Iterator), repr(x))
143 self.failIf(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000144 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000145 iter(tuple()), iter(list()), iter(dict()),
146 iter(set()), iter(frozenset()),
147 iter(dict().keys()), iter(dict().items()),
148 iter(dict().values()),
149 (lambda: (yield))(),
150 (x for x in []),
151 ]
152 for x in samples:
153 self.failUnless(isinstance(x, Iterator), repr(x))
154 self.failUnless(issubclass(type(x), Iterator), repr(type(x)))
155
156 def test_Sized(self):
157 non_samples = [None, 42, 3.14, 1j,
158 (lambda: (yield))(),
159 (x for x in []),
160 ]
161 for x in non_samples:
162 self.failIf(isinstance(x, Sized), repr(x))
163 self.failIf(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000164 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000165 tuple(), list(), set(), frozenset(), dict(),
166 dict().keys(), dict().items(), dict().values(),
167 ]
168 for x in samples:
169 self.failUnless(isinstance(x, Sized), repr(x))
170 self.failUnless(issubclass(type(x), Sized), repr(type(x)))
171
172 def test_Container(self):
173 non_samples = [None, 42, 3.14, 1j,
174 (lambda: (yield))(),
175 (x for x in []),
176 ]
177 for x in non_samples:
178 self.failIf(isinstance(x, Container), repr(x))
179 self.failIf(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000180 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000181 tuple(), list(), set(), frozenset(), dict(),
182 dict().keys(), dict().items(),
183 ]
184 for x in samples:
185 self.failUnless(isinstance(x, Container), repr(x))
186 self.failUnless(issubclass(type(x), Container), repr(type(x)))
187
188 def test_Callable(self):
189 non_samples = [None, 42, 3.14, 1j,
190 "", b"", (), [], {}, set(),
191 (lambda: (yield))(),
192 (x for x in []),
193 ]
194 for x in non_samples:
195 self.failIf(isinstance(x, Callable), repr(x))
196 self.failIf(issubclass(type(x), Callable), repr(type(x)))
197 samples = [lambda: None,
198 type, int, object,
199 len,
200 list.append, [].append,
201 ]
202 for x in samples:
203 self.failUnless(isinstance(x, Callable), repr(x))
204 self.failUnless(issubclass(type(x), Callable), repr(type(x)))
205
206 def test_direct_subclassing(self):
207 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
208 class C(B):
209 pass
210 self.failUnless(issubclass(C, B))
211 self.failIf(issubclass(int, C))
212
213 def test_registration(self):
214 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
215 class C:
216 __hash__ = None # Make sure it isn't hashable by default
217 self.failIf(issubclass(C, B), B.__name__)
218 B.register(C)
219 self.failUnless(issubclass(C, B))
220
221
222class TestCollectionABCs(unittest.TestCase):
223
224 # XXX For now, we only test some virtual inheritance properties.
225 # We should also test the proper behavior of the collection ABCs
226 # as real base classes or mix-in classes.
227
228 def test_Set(self):
229 for sample in [set, frozenset]:
230 self.failUnless(isinstance(sample(), Set))
231 self.failUnless(issubclass(sample, Set))
232
233 def test_MutableSet(self):
234 self.failUnless(isinstance(set(), MutableSet))
235 self.failUnless(issubclass(set, MutableSet))
236 self.failIf(isinstance(frozenset(), MutableSet))
237 self.failIf(issubclass(frozenset, MutableSet))
238
239 def test_Mapping(self):
240 for sample in [dict]:
241 self.failUnless(isinstance(sample(), Mapping))
242 self.failUnless(issubclass(sample, Mapping))
243
244 def test_MutableMapping(self):
245 for sample in [dict]:
246 self.failUnless(isinstance(sample(), MutableMapping))
247 self.failUnless(issubclass(sample, MutableMapping))
248
249 def test_Sequence(self):
250 for sample in [tuple, list, bytes, str]:
251 self.failUnless(isinstance(sample(), Sequence))
252 self.failUnless(issubclass(sample, Sequence))
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000253 self.failUnless(issubclass(str, Sequence))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000254
255 def test_MutableSequence(self):
256 for sample in [tuple, str]:
257 self.failIf(isinstance(sample(), MutableSequence))
258 self.failIf(issubclass(sample, MutableSequence))
259 for sample in [list, bytes]:
260 self.failUnless(isinstance(sample(), MutableSequence))
261 self.failUnless(issubclass(sample, MutableSequence))
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000262 self.failIf(issubclass(str, MutableSequence))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000263
264
Guido van Rossumd8faa362007-04-27 19:54:29 +0000265def test_main(verbose=None):
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000266 import collections as CollectionsModule
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000267 test_classes = [TestNamedTuple, TestOneTrickPonyABCs, TestCollectionABCs]
Guido van Rossumd8faa362007-04-27 19:54:29 +0000268 test_support.run_unittest(*test_classes)
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000269 test_support.run_doctest(CollectionsModule, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000270
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000271
Guido van Rossumd8faa362007-04-27 19:54:29 +0000272if __name__ == "__main__":
273 test_main(verbose=True)