blob: ec10752e6a2ae0eac233c1cdd9bf7cd8ed858b54 [file] [log] [blame]
Guido van Rossum85f18201992-11-27 22:53:50 +00001# Python test set -- part 6, built-in types
2
Benjamin Petersonee8712c2008-05-20 21:35:26 +00003from test.support import run_unittest, run_with_locale
Victor Stinner0db176f2012-04-16 00:16:30 +02004import collections
Eric Snowb5c8f922013-02-16 16:32:39 -07005import pickle
Eric Smithb2c7af82008-04-30 02:12:09 +00006import locale
Victor Stinner0db176f2012-04-16 00:16:30 +02007import sys
8import types
9import unittest
Guido van Rossum85f18201992-11-27 22:53:50 +000010
Thomas Wouters89f507f2006-12-13 04:49:30 +000011class TypesTests(unittest.TestCase):
Guido van Rossum85f18201992-11-27 22:53:50 +000012
Thomas Wouters89f507f2006-12-13 04:49:30 +000013 def test_truth_values(self):
14 if None: self.fail('None is true instead of false')
15 if 0: self.fail('0 is true instead of false')
Thomas Wouters89f507f2006-12-13 04:49:30 +000016 if 0.0: self.fail('0.0 is true instead of false')
17 if '': self.fail('\'\' is true instead of false')
18 if not 1: self.fail('1 is false instead of true')
Thomas Wouters89f507f2006-12-13 04:49:30 +000019 if not 1.0: self.fail('1.0 is false instead of true')
20 if not 'x': self.fail('\'x\' is false instead of true')
21 if not {'x': 1}: self.fail('{\'x\': 1} is false instead of true')
22 def f(): pass
23 class C: pass
Thomas Wouters89f507f2006-12-13 04:49:30 +000024 x = C()
25 if not f: self.fail('f is false instead of true')
26 if not C: self.fail('C is false instead of true')
27 if not sys: self.fail('sys is false instead of true')
28 if not x: self.fail('x is false instead of true')
Guido van Rossum85f18201992-11-27 22:53:50 +000029
Thomas Wouters89f507f2006-12-13 04:49:30 +000030 def test_boolean_ops(self):
31 if 0 or 0: self.fail('0 or 0 is true instead of false')
32 if 1 and 1: pass
33 else: self.fail('1 and 1 is false instead of true')
34 if not 1: self.fail('not 1 is true instead of false')
Neil Schemenauereff72442002-03-24 01:24:54 +000035
Thomas Wouters89f507f2006-12-13 04:49:30 +000036 def test_comparisons(self):
37 if 0 < 1 <= 1 == 1 >= 1 > 0 != 1: pass
38 else: self.fail('int comparisons failed')
Thomas Wouters89f507f2006-12-13 04:49:30 +000039 if 0.0 < 1.0 <= 1.0 == 1.0 >= 1.0 > 0.0 != 1.0: pass
40 else: self.fail('float comparisons failed')
41 if '' < 'a' <= 'a' == 'a' < 'abc' < 'abd' < 'b': pass
42 else: self.fail('string comparisons failed')
43 if None is None: pass
44 else: self.fail('identity test failed')
Neil Schemenauereff72442002-03-24 01:24:54 +000045
Thomas Wouters89f507f2006-12-13 04:49:30 +000046 def test_float_constructor(self):
47 self.assertRaises(ValueError, float, '')
48 self.assertRaises(ValueError, float, '5\0')
Neil Schemenauereff72442002-03-24 01:24:54 +000049
Thomas Wouters89f507f2006-12-13 04:49:30 +000050 def test_zero_division(self):
51 try: 5.0 / 0.0
52 except ZeroDivisionError: pass
53 else: self.fail("5.0 / 0.0 didn't raise ZeroDivisionError")
Neil Schemenauereff72442002-03-24 01:24:54 +000054
Thomas Wouters89f507f2006-12-13 04:49:30 +000055 try: 5.0 // 0.0
56 except ZeroDivisionError: pass
57 else: self.fail("5.0 // 0.0 didn't raise ZeroDivisionError")
Neil Schemenauereff72442002-03-24 01:24:54 +000058
Thomas Wouters89f507f2006-12-13 04:49:30 +000059 try: 5.0 % 0.0
60 except ZeroDivisionError: pass
61 else: self.fail("5.0 % 0.0 didn't raise ZeroDivisionError")
Neil Schemenauereff72442002-03-24 01:24:54 +000062
Guido van Rossume2a383d2007-01-15 16:59:06 +000063 try: 5 / 0
Thomas Wouters89f507f2006-12-13 04:49:30 +000064 except ZeroDivisionError: pass
Christian Heimes7131fd92008-02-19 14:21:46 +000065 else: self.fail("5 / 0 didn't raise ZeroDivisionError")
Neil Schemenauereff72442002-03-24 01:24:54 +000066
Guido van Rossume2a383d2007-01-15 16:59:06 +000067 try: 5 // 0
Thomas Wouters89f507f2006-12-13 04:49:30 +000068 except ZeroDivisionError: pass
Christian Heimes7131fd92008-02-19 14:21:46 +000069 else: self.fail("5 // 0 didn't raise ZeroDivisionError")
Neil Schemenauereff72442002-03-24 01:24:54 +000070
Guido van Rossume2a383d2007-01-15 16:59:06 +000071 try: 5 % 0
Thomas Wouters89f507f2006-12-13 04:49:30 +000072 except ZeroDivisionError: pass
Christian Heimes7131fd92008-02-19 14:21:46 +000073 else: self.fail("5 % 0 didn't raise ZeroDivisionError")
Tim Petersa3c01ce2001-12-04 23:05:10 +000074
Thomas Wouters89f507f2006-12-13 04:49:30 +000075 def test_numeric_types(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +000076 if 0 != 0.0 or 1 != 1.0 or -1 != -1.0:
77 self.fail('int/float value not equal')
Thomas Wouters89f507f2006-12-13 04:49:30 +000078 # calling built-in types without argument must return 0
79 if int() != 0: self.fail('int() does not return 0')
Thomas Wouters89f507f2006-12-13 04:49:30 +000080 if float() != 0.0: self.fail('float() does not return 0.0')
81 if int(1.9) == 1 == int(1.1) and int(-1.1) == -1 == int(-1.9): pass
82 else: self.fail('int() does not round properly')
Thomas Wouters89f507f2006-12-13 04:49:30 +000083 if float(1) == 1.0 and float(-1) == -1.0 and float(0) == 0.0: pass
84 else: self.fail('float() does not work properly')
Neil Schemenauereff72442002-03-24 01:24:54 +000085
Christian Heimesc3f30c42008-02-22 16:37:40 +000086 def test_float_to_string(self):
87 def test(f, result):
88 self.assertEqual(f.__format__('e'), result)
89 self.assertEqual('%e' % f, result)
90
91 # test all 2 digit exponents, both with __format__ and with
92 # '%' formatting
93 for i in range(-99, 100):
94 test(float('1.5e'+str(i)), '1.500000e{0:+03d}'.format(i))
95
96 # test some 3 digit exponents
97 self.assertEqual(1.5e100.__format__('e'), '1.500000e+100')
98 self.assertEqual('%e' % 1.5e100, '1.500000e+100')
99
100 self.assertEqual(1.5e101.__format__('e'), '1.500000e+101')
101 self.assertEqual('%e' % 1.5e101, '1.500000e+101')
102
103 self.assertEqual(1.5e-100.__format__('e'), '1.500000e-100')
104 self.assertEqual('%e' % 1.5e-100, '1.500000e-100')
105
106 self.assertEqual(1.5e-101.__format__('e'), '1.500000e-101')
107 self.assertEqual('%e' % 1.5e-101, '1.500000e-101')
108
Eric Smith0923d1d2009-04-16 20:16:10 +0000109 self.assertEqual('%g' % 1.0, '1')
110 self.assertEqual('%#g' % 1.0, '1.00000')
111
Thomas Wouters89f507f2006-12-13 04:49:30 +0000112 def test_normal_integers(self):
113 # Ensure the first 256 integers are shared
114 a = 256
115 b = 128*2
116 if a is not b: self.fail('256 is not shared')
117 if 12 + 24 != 36: self.fail('int op')
118 if 12 + (-24) != -12: self.fail('int op')
119 if (-12) + 24 != 12: self.fail('int op')
120 if (-12) + (-24) != -36: self.fail('int op')
121 if not 12 < 24: self.fail('int op')
122 if not -24 < -12: self.fail('int op')
123 # Test for a particular bug in integer multiply
124 xsize, ysize, zsize = 238, 356, 4
125 if not (xsize*ysize*zsize == zsize*xsize*ysize == 338912):
126 self.fail('int mul commutativity')
127 # And another.
Christian Heimesa37d4c62007-12-04 23:02:19 +0000128 m = -sys.maxsize - 1
Thomas Wouters89f507f2006-12-13 04:49:30 +0000129 for divisor in 1, 2, 4, 8, 16, 32:
130 j = m // divisor
131 prod = divisor * j
132 if prod != m:
133 self.fail("%r * %r == %r != %r" % (divisor, j, prod, m))
134 if type(prod) is not int:
135 self.fail("expected type(prod) to be int, not %r" %
136 type(prod))
Mark Dickinson5c2db372009-12-05 20:28:34 +0000137 # Check for unified integral type
Thomas Wouters89f507f2006-12-13 04:49:30 +0000138 for divisor in 1, 2, 4, 8, 16, 32:
139 j = m // divisor - 1
140 prod = divisor * j
Guido van Rossume2a383d2007-01-15 16:59:06 +0000141 if type(prod) is not int:
Mark Dickinson5c2db372009-12-05 20:28:34 +0000142 self.fail("expected type(%r) to be int, not %r" %
Thomas Wouters89f507f2006-12-13 04:49:30 +0000143 (prod, type(prod)))
Mark Dickinson5c2db372009-12-05 20:28:34 +0000144 # Check for unified integral type
Christian Heimesa37d4c62007-12-04 23:02:19 +0000145 m = sys.maxsize
Thomas Wouters89f507f2006-12-13 04:49:30 +0000146 for divisor in 1, 2, 4, 8, 16, 32:
147 j = m // divisor + 1
148 prod = divisor * j
Guido van Rossume2a383d2007-01-15 16:59:06 +0000149 if type(prod) is not int:
Mark Dickinson5c2db372009-12-05 20:28:34 +0000150 self.fail("expected type(%r) to be int, not %r" %
Thomas Wouters89f507f2006-12-13 04:49:30 +0000151 (prod, type(prod)))
Neil Schemenauereff72442002-03-24 01:24:54 +0000152
Christian Heimesa37d4c62007-12-04 23:02:19 +0000153 x = sys.maxsize
Ezio Melottie9615932010-01-24 19:26:24 +0000154 self.assertIsInstance(x + 1, int,
155 "(sys.maxsize + 1) should have returned int")
156 self.assertIsInstance(-x - 1, int,
157 "(-sys.maxsize - 1) should have returned int")
158 self.assertIsInstance(-x - 2, int,
159 "(-sys.maxsize - 2) should have returned int")
Neil Schemenauereff72442002-03-24 01:24:54 +0000160
Thomas Wouters89f507f2006-12-13 04:49:30 +0000161 try: 5 << -5
162 except ValueError: pass
163 else: self.fail('int negative shift <<')
Neil Schemenauereff72442002-03-24 01:24:54 +0000164
Thomas Wouters89f507f2006-12-13 04:49:30 +0000165 try: 5 >> -5
166 except ValueError: pass
167 else: self.fail('int negative shift >>')
Guido van Rossum85f18201992-11-27 22:53:50 +0000168
Thomas Wouters89f507f2006-12-13 04:49:30 +0000169 def test_floats(self):
170 if 12.0 + 24.0 != 36.0: self.fail('float op')
171 if 12.0 + (-24.0) != -12.0: self.fail('float op')
172 if (-12.0) + 24.0 != 12.0: self.fail('float op')
173 if (-12.0) + (-24.0) != -36.0: self.fail('float op')
174 if not 12.0 < 24.0: self.fail('float op')
175 if not -24.0 < -12.0: self.fail('float op')
Guido van Rossum85f18201992-11-27 22:53:50 +0000176
Thomas Wouters89f507f2006-12-13 04:49:30 +0000177 def test_strings(self):
178 if len('') != 0: self.fail('len(\'\')')
179 if len('a') != 1: self.fail('len(\'a\')')
180 if len('abcdef') != 6: self.fail('len(\'abcdef\')')
181 if 'xyz' + 'abcde' != 'xyzabcde': self.fail('string concatenation')
182 if 'xyz'*3 != 'xyzxyzxyz': self.fail('string repetition *3')
183 if 0*'abcde' != '': self.fail('string repetition 0*')
184 if min('abc') != 'a' or max('abc') != 'c': self.fail('min/max string')
185 if 'a' in 'abc' and 'b' in 'abc' and 'c' in 'abc' and 'd' not in 'abc': pass
186 else: self.fail('in/not in string')
187 x = 'x'*103
188 if '%s!'%x != x+'!': self.fail('nasty string formatting bug')
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000189
Thomas Wouters89f507f2006-12-13 04:49:30 +0000190 #extended slices for strings
191 a = '0123456789'
192 self.assertEqual(a[::], a)
193 self.assertEqual(a[::2], '02468')
194 self.assertEqual(a[1::2], '13579')
195 self.assertEqual(a[::-1],'9876543210')
196 self.assertEqual(a[::-2], '97531')
197 self.assertEqual(a[3::-2], '31')
198 self.assertEqual(a[-100:100:], a)
199 self.assertEqual(a[100:-100:-1], a[::-1])
Guido van Rossume2a383d2007-01-15 16:59:06 +0000200 self.assertEqual(a[-100:100:2], '02468')
Thomas Wouters89f507f2006-12-13 04:49:30 +0000201
Thomas Wouters89f507f2006-12-13 04:49:30 +0000202 def test_type_function(self):
203 self.assertRaises(TypeError, type, 1, 2)
204 self.assertRaises(TypeError, type, 1, 2, 3, 4)
Guido van Rossum85f18201992-11-27 22:53:50 +0000205
Christian Heimes7131fd92008-02-19 14:21:46 +0000206 def test_int__format__(self):
207 def test(i, format_spec, result):
Mark Dickinson5c2db372009-12-05 20:28:34 +0000208 # just make sure we have the unified type for integers
Christian Heimes7131fd92008-02-19 14:21:46 +0000209 assert type(i) == int
210 assert type(format_spec) == str
211 self.assertEqual(i.__format__(format_spec), result)
212
213 test(123456789, 'd', '123456789')
214 test(123456789, 'd', '123456789')
215
216 test(1, 'c', '\01')
217
218 # sign and aligning are interdependent
219 test(1, "-", '1')
220 test(-1, "-", '-1')
221 test(1, "-3", ' 1')
222 test(-1, "-3", ' -1')
223 test(1, "+3", ' +1')
224 test(-1, "+3", ' -1')
225 test(1, " 3", ' 1')
226 test(-1, " 3", ' -1')
227 test(1, " ", ' 1')
228 test(-1, " ", '-1')
229
230 # hex
231 test(3, "x", "3")
232 test(3, "X", "3")
233 test(1234, "x", "4d2")
234 test(-1234, "x", "-4d2")
235 test(1234, "8x", " 4d2")
236 test(-1234, "8x", " -4d2")
237 test(1234, "x", "4d2")
238 test(-1234, "x", "-4d2")
239 test(-3, "x", "-3")
240 test(-3, "X", "-3")
241 test(int('be', 16), "x", "be")
242 test(int('be', 16), "X", "BE")
243 test(-int('be', 16), "x", "-be")
244 test(-int('be', 16), "X", "-BE")
245
246 # octal
247 test(3, "o", "3")
248 test(-3, "o", "-3")
249 test(65, "o", "101")
250 test(-65, "o", "-101")
251 test(1234, "o", "2322")
252 test(-1234, "o", "-2322")
253 test(1234, "-o", "2322")
254 test(-1234, "-o", "-2322")
255 test(1234, " o", " 2322")
256 test(-1234, " o", "-2322")
257 test(1234, "+o", "+2322")
258 test(-1234, "+o", "-2322")
259
260 # binary
261 test(3, "b", "11")
262 test(-3, "b", "-11")
263 test(1234, "b", "10011010010")
264 test(-1234, "b", "-10011010010")
265 test(1234, "-b", "10011010010")
266 test(-1234, "-b", "-10011010010")
267 test(1234, " b", " 10011010010")
268 test(-1234, " b", "-10011010010")
269 test(1234, "+b", "+10011010010")
270 test(-1234, "+b", "-10011010010")
271
Eric Smithb1ebcc62008-07-15 13:02:41 +0000272 # alternate (#) formatting
273 test(0, "#b", '0b0')
274 test(0, "-#b", '0b0')
275 test(1, "-#b", '0b1')
276 test(-1, "-#b", '-0b1')
277 test(-1, "-#5b", ' -0b1')
278 test(1, "+#5b", ' +0b1')
279 test(100, "+#b", '+0b1100100')
Eric Smithd68af8f2008-07-16 00:15:35 +0000280 test(100, "#012b", '0b0001100100')
281 test(-100, "#012b", '-0b001100100')
Eric Smithb1ebcc62008-07-15 13:02:41 +0000282
283 test(0, "#o", '0o0')
284 test(0, "-#o", '0o0')
285 test(1, "-#o", '0o1')
286 test(-1, "-#o", '-0o1')
287 test(-1, "-#5o", ' -0o1')
288 test(1, "+#5o", ' +0o1')
289 test(100, "+#o", '+0o144')
Eric Smithd68af8f2008-07-16 00:15:35 +0000290 test(100, "#012o", '0o0000000144')
291 test(-100, "#012o", '-0o000000144')
Eric Smithb1ebcc62008-07-15 13:02:41 +0000292
293 test(0, "#x", '0x0')
294 test(0, "-#x", '0x0')
295 test(1, "-#x", '0x1')
296 test(-1, "-#x", '-0x1')
297 test(-1, "-#5x", ' -0x1')
298 test(1, "+#5x", ' +0x1')
299 test(100, "+#x", '+0x64')
Eric Smithd68af8f2008-07-16 00:15:35 +0000300 test(100, "#012x", '0x0000000064')
301 test(-100, "#012x", '-0x000000064')
302 test(123456, "#012x", '0x000001e240')
303 test(-123456, "#012x", '-0x00001e240')
Eric Smithb1ebcc62008-07-15 13:02:41 +0000304
305 test(0, "#X", '0X0')
306 test(0, "-#X", '0X0')
307 test(1, "-#X", '0X1')
308 test(-1, "-#X", '-0X1')
309 test(-1, "-#5X", ' -0X1')
310 test(1, "+#5X", ' +0X1')
311 test(100, "+#X", '+0X64')
Eric Smithd68af8f2008-07-16 00:15:35 +0000312 test(100, "#012X", '0X0000000064')
313 test(-100, "#012X", '-0X000000064')
314 test(123456, "#012X", '0X000001E240')
315 test(-123456, "#012X", '-0X00001E240')
Eric Smithb1ebcc62008-07-15 13:02:41 +0000316
Eric Smitha3b1ac82009-04-03 14:45:06 +0000317 test(123, ',', '123')
318 test(-123, ',', '-123')
319 test(1234, ',', '1,234')
320 test(-1234, ',', '-1,234')
321 test(123456, ',', '123,456')
322 test(-123456, ',', '-123,456')
323 test(1234567, ',', '1,234,567')
324 test(-1234567, ',', '-1,234,567')
325
Eric Smith937491d2009-04-22 17:04:27 +0000326 # issue 5782, commas with no specifier type
327 test(1234, '010,', '00,001,234')
328
Mark Dickinson5c2db372009-12-05 20:28:34 +0000329 # Unified type for integers
330 test(10**100, 'd', '1' + '0' * 100)
331 test(10**100+100, 'd', '1' + '0' * 97 + '100')
332
Christian Heimes7131fd92008-02-19 14:21:46 +0000333 # make sure these are errors
334
335 # precision disallowed
336 self.assertRaises(ValueError, 3 .__format__, "1.3")
337 # sign not allowed with 'c'
338 self.assertRaises(ValueError, 3 .__format__, "+c")
339 # format spec must be string
340 self.assertRaises(TypeError, 3 .__format__, None)
341 self.assertRaises(TypeError, 3 .__format__, 0)
Eric Smitha3b1ac82009-04-03 14:45:06 +0000342 # can't have ',' with 'n'
343 self.assertRaises(ValueError, 3 .__format__, ",n")
Eric Smith0923d1d2009-04-16 20:16:10 +0000344 # can't have ',' with 'c'
345 self.assertRaises(ValueError, 3 .__format__, ",c")
Christian Heimes7131fd92008-02-19 14:21:46 +0000346
347 # ensure that only int and float type specifiers work
348 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
349 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
350 if not format_spec in 'bcdoxXeEfFgGn%':
351 self.assertRaises(ValueError, 0 .__format__, format_spec)
352 self.assertRaises(ValueError, 1 .__format__, format_spec)
353 self.assertRaises(ValueError, (-1) .__format__, format_spec)
354
355 # ensure that float type specifiers work; format converts
356 # the int to a float
Eric Smith5807c412008-05-11 21:00:57 +0000357 for format_spec in 'eEfFgG%':
Christian Heimes7131fd92008-02-19 14:21:46 +0000358 for value in [0, 1, -1, 100, -100, 1234567890, -1234567890]:
359 self.assertEqual(value.__format__(format_spec),
360 float(value).__format__(format_spec))
361
Eric Smithabb28c62010-02-23 00:22:24 +0000362 # Issue 6902
363 test(123456, "0<20", '12345600000000000000')
364 test(123456, "1<20", '12345611111111111111')
365 test(123456, "*<20", '123456**************')
366 test(123456, "0>20", '00000000000000123456')
367 test(123456, "1>20", '11111111111111123456')
368 test(123456, "*>20", '**************123456')
369 test(123456, "0=20", '00000000000000123456')
370 test(123456, "1=20", '11111111111111123456')
371 test(123456, "*=20", '**************123456')
372
Eric Smithb2c7af82008-04-30 02:12:09 +0000373 @run_with_locale('LC_NUMERIC', 'en_US.UTF8')
374 def test_float__format__locale(self):
375 # test locale support for __format__ code 'n'
376
377 for i in range(-10, 10):
378 x = 1234567890.0 * (10.0 ** i)
379 self.assertEqual(locale.format('%g', x, grouping=True), format(x, 'n'))
380 self.assertEqual(locale.format('%.10g', x, grouping=True), format(x, '.10n'))
381
Eric Smith5807c412008-05-11 21:00:57 +0000382 @run_with_locale('LC_NUMERIC', 'en_US.UTF8')
383 def test_int__format__locale(self):
384 # test locale support for __format__ code 'n' for integers
385
386 x = 123456789012345678901234567890
387 for i in range(0, 30):
388 self.assertEqual(locale.format('%d', x, grouping=True), format(x, 'n'))
389
390 # move to the next integer to test
391 x = x // 10
392
Eric Smithb151a452008-06-24 11:21:04 +0000393 rfmt = ">20n"
394 lfmt = "<20n"
395 cfmt = "^20n"
396 for x in (1234, 12345, 123456, 1234567, 12345678, 123456789, 1234567890, 12345678900):
397 self.assertEqual(len(format(0, rfmt)), len(format(x, rfmt)))
398 self.assertEqual(len(format(0, lfmt)), len(format(x, lfmt)))
399 self.assertEqual(len(format(0, cfmt)), len(format(x, cfmt)))
400
Christian Heimes7131fd92008-02-19 14:21:46 +0000401 def test_float__format__(self):
Christian Heimes7131fd92008-02-19 14:21:46 +0000402 def test(f, format_spec, result):
Christian Heimes7131fd92008-02-19 14:21:46 +0000403 self.assertEqual(f.__format__(format_spec), result)
Eric Smith984bb582010-11-25 16:08:06 +0000404 self.assertEqual(format(f, format_spec), result)
Christian Heimes7131fd92008-02-19 14:21:46 +0000405
406 test(0.0, 'f', '0.000000')
407
408 # the default is 'g', except for empty format spec
409 test(0.0, '', '0.0')
410 test(0.01, '', '0.01')
411 test(0.01, 'g', '0.01')
412
Eric Smith2ad79e82008-07-19 00:33:23 +0000413 # test for issue 3411
414 test(1.23, '1', '1.23')
415 test(-1.23, '1', '-1.23')
416 test(1.23, '1g', '1.23')
417 test(-1.23, '1g', '-1.23')
418
Christian Heimes7131fd92008-02-19 14:21:46 +0000419 test( 1.0, ' g', ' 1')
420 test(-1.0, ' g', '-1')
421 test( 1.0, '+g', '+1')
422 test(-1.0, '+g', '-1')
423 test(1.1234e200, 'g', '1.1234e+200')
424 test(1.1234e200, 'G', '1.1234E+200')
425
426
427 test(1.0, 'f', '1.000000')
428
429 test(-1.0, 'f', '-1.000000')
430
431 test( 1.0, ' f', ' 1.000000')
432 test(-1.0, ' f', '-1.000000')
433 test( 1.0, '+f', '+1.000000')
434 test(-1.0, '+f', '-1.000000')
Mark Dickinson33841c32009-05-01 15:37:04 +0000435
436 # Python versions <= 3.0 switched from 'f' to 'g' formatting for
437 # values larger than 1e50. No longer.
438 f = 1.1234e90
439 for fmt in 'f', 'F':
440 # don't do a direct equality check, since on some
441 # platforms only the first few digits of dtoa
442 # will be reliable
443 result = f.__format__(fmt)
444 self.assertEqual(len(result), 98)
445 self.assertEqual(result[-7], '.')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000446 self.assertIn(result[:12], ('112340000000', '112339999999'))
Mark Dickinson33841c32009-05-01 15:37:04 +0000447 f = 1.1234e200
448 for fmt in 'f', 'F':
449 result = f.__format__(fmt)
450 self.assertEqual(len(result), 208)
451 self.assertEqual(result[-7], '.')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000452 self.assertIn(result[:12], ('112340000000', '112339999999'))
Mark Dickinson33841c32009-05-01 15:37:04 +0000453
Christian Heimes7131fd92008-02-19 14:21:46 +0000454
Christian Heimesc3f30c42008-02-22 16:37:40 +0000455 test( 1.0, 'e', '1.000000e+00')
456 test(-1.0, 'e', '-1.000000e+00')
457 test( 1.0, 'E', '1.000000E+00')
458 test(-1.0, 'E', '-1.000000E+00')
459 test(1.1234e20, 'e', '1.123400e+20')
460 test(1.1234e20, 'E', '1.123400E+20')
Christian Heimes7131fd92008-02-19 14:21:46 +0000461
Christian Heimesb186d002008-03-18 15:15:01 +0000462 # No format code means use g, but must have a decimal
463 # and a number after the decimal. This is tricky, because
464 # a totaly empty format specifier means something else.
465 # So, just use a sign flag
466 test(1e200, '+g', '+1e+200')
Eric Smith0923d1d2009-04-16 20:16:10 +0000467 test(1e200, '+', '+1e+200')
468
Christian Heimesb186d002008-03-18 15:15:01 +0000469 test(1.1e200, '+g', '+1.1e+200')
470 test(1.1e200, '+', '+1.1e+200')
471
Eric Smith0923d1d2009-04-16 20:16:10 +0000472 # 0 padding
473 test(1234., '010f', '1234.000000')
474 test(1234., '011f', '1234.000000')
475 test(1234., '012f', '01234.000000')
476 test(-1234., '011f', '-1234.000000')
477 test(-1234., '012f', '-1234.000000')
478 test(-1234., '013f', '-01234.000000')
479 test(-1234.12341234, '013f', '-01234.123412')
480 test(-123456.12341234, '011.2f', '-0123456.12')
481
Eric Smith937491d2009-04-22 17:04:27 +0000482 # issue 5782, commas with no specifier type
483 test(1.2, '010,.2', '0,000,001.2')
484
Eric Smith0923d1d2009-04-16 20:16:10 +0000485 # 0 padding with commas
486 test(1234., '011,f', '1,234.000000')
487 test(1234., '012,f', '1,234.000000')
488 test(1234., '013,f', '01,234.000000')
489 test(-1234., '012,f', '-1,234.000000')
490 test(-1234., '013,f', '-1,234.000000')
491 test(-1234., '014,f', '-01,234.000000')
492 test(-12345., '015,f', '-012,345.000000')
493 test(-123456., '016,f', '-0,123,456.000000')
494 test(-123456., '017,f', '-0,123,456.000000')
495 test(-123456.12341234, '017,f', '-0,123,456.123412')
496 test(-123456.12341234, '013,.2f', '-0,123,456.12')
497
Christian Heimes7131fd92008-02-19 14:21:46 +0000498 # % formatting
499 test(-1.0, '%', '-100.000000%')
500
501 # format spec must be string
502 self.assertRaises(TypeError, 3.0.__format__, None)
503 self.assertRaises(TypeError, 3.0.__format__, 0)
504
505 # other format specifiers shouldn't work on floats,
506 # in particular int specifiers
507 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
508 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
509 if not format_spec in 'eEfFgGn%':
510 self.assertRaises(ValueError, format, 0.0, format_spec)
511 self.assertRaises(ValueError, format, 1.0, format_spec)
512 self.assertRaises(ValueError, format, -1.0, format_spec)
513 self.assertRaises(ValueError, format, 1e100, format_spec)
514 self.assertRaises(ValueError, format, -1e100, format_spec)
515 self.assertRaises(ValueError, format, 1e-100, format_spec)
516 self.assertRaises(ValueError, format, -1e-100, format_spec)
517
Eric Smith984bb582010-11-25 16:08:06 +0000518 # Alternate float formatting
519 test(1.0, '.0e', '1e+00')
520 test(1.0, '#.0e', '1.e+00')
521 test(1.0, '.0f', '1')
522 test(1.0, '#.0f', '1.')
523 test(1.1, 'g', '1.1')
524 test(1.1, '#g', '1.10000')
525 test(1.0, '.0%', '100%')
526 test(1.0, '#.0%', '100.%')
527
528 # Issue 7094: Alternate formatting (specified by #)
529 test(1.0, '0e', '1.000000e+00')
530 test(1.0, '#0e', '1.000000e+00')
531 test(1.0, '0f', '1.000000' )
532 test(1.0, '#0f', '1.000000')
533 test(1.0, '.1e', '1.0e+00')
534 test(1.0, '#.1e', '1.0e+00')
535 test(1.0, '.1f', '1.0')
536 test(1.0, '#.1f', '1.0')
537 test(1.0, '.1%', '100.0%')
538 test(1.0, '#.1%', '100.0%')
Eric Smithb1ebcc62008-07-15 13:02:41 +0000539
Eric Smithabb28c62010-02-23 00:22:24 +0000540 # Issue 6902
541 test(12345.6, "0<20", '12345.60000000000000')
542 test(12345.6, "1<20", '12345.61111111111111')
543 test(12345.6, "*<20", '12345.6*************')
544 test(12345.6, "0>20", '000000000000012345.6')
545 test(12345.6, "1>20", '111111111111112345.6')
546 test(12345.6, "*>20", '*************12345.6')
547 test(12345.6, "0=20", '000000000000012345.6')
548 test(12345.6, "1=20", '111111111111112345.6')
549 test(12345.6, "*=20", '*************12345.6')
550
Eric Smith0923d1d2009-04-16 20:16:10 +0000551 def test_format_spec_errors(self):
552 # int, float, and string all share the same format spec
553 # mini-language parser.
554
555 # Check that we can't ask for too many digits. This is
556 # probably a CPython specific test. It tries to put the width
557 # into a C long.
558 self.assertRaises(ValueError, format, 0, '1'*10000 + 'd')
559
560 # Similar with the precision.
561 self.assertRaises(ValueError, format, 0, '.' + '1'*10000 + 'd')
562
563 # And may as well test both.
564 self.assertRaises(ValueError, format, 0, '1'*1000 + '.' + '1'*10000 + 'd')
565
566 # Make sure commas aren't allowed with various type codes
567 for code in 'xXobns':
568 self.assertRaises(ValueError, format, 0, ',' + code)
Christian Heimes7131fd92008-02-19 14:21:46 +0000569
Benjamin Peterson0e102062010-08-25 23:13:17 +0000570 def test_internal_sizes(self):
571 self.assertGreater(object.__basicsize__, 0)
572 self.assertGreater(tuple.__itemsize__, 0)
573
574
Victor Stinner0db176f2012-04-16 00:16:30 +0200575class MappingProxyTests(unittest.TestCase):
576 mappingproxy = types.MappingProxyType
577
578 def test_constructor(self):
579 class userdict(dict):
580 pass
581
582 mapping = {'x': 1, 'y': 2}
583 self.assertEqual(self.mappingproxy(mapping), mapping)
584 mapping = userdict(x=1, y=2)
585 self.assertEqual(self.mappingproxy(mapping), mapping)
586 mapping = collections.ChainMap({'x': 1}, {'y': 2})
587 self.assertEqual(self.mappingproxy(mapping), mapping)
588
589 self.assertRaises(TypeError, self.mappingproxy, 10)
590 self.assertRaises(TypeError, self.mappingproxy, ("a", "tuple"))
591 self.assertRaises(TypeError, self.mappingproxy, ["a", "list"])
592
593 def test_methods(self):
594 attrs = set(dir(self.mappingproxy({}))) - set(dir(object()))
595 self.assertEqual(attrs, {
596 '__contains__',
597 '__getitem__',
598 '__iter__',
599 '__len__',
600 'copy',
601 'get',
602 'items',
603 'keys',
604 'values',
605 })
606
607 def test_get(self):
608 view = self.mappingproxy({'a': 'A', 'b': 'B'})
609 self.assertEqual(view['a'], 'A')
610 self.assertEqual(view['b'], 'B')
611 self.assertRaises(KeyError, view.__getitem__, 'xxx')
612 self.assertEqual(view.get('a'), 'A')
613 self.assertIsNone(view.get('xxx'))
614 self.assertEqual(view.get('xxx', 42), 42)
615
616 def test_missing(self):
617 class dictmissing(dict):
618 def __missing__(self, key):
619 return "missing=%s" % key
620
621 view = self.mappingproxy(dictmissing(x=1))
622 self.assertEqual(view['x'], 1)
623 self.assertEqual(view['y'], 'missing=y')
624 self.assertEqual(view.get('x'), 1)
625 self.assertEqual(view.get('y'), None)
626 self.assertEqual(view.get('y', 42), 42)
627 self.assertTrue('x' in view)
628 self.assertFalse('y' in view)
629
630 def test_customdict(self):
631 class customdict(dict):
632 def __contains__(self, key):
633 if key == 'magic':
634 return True
635 else:
636 return dict.__contains__(self, key)
637
638 def __iter__(self):
639 return iter(('iter',))
640
641 def __len__(self):
642 return 500
643
644 def copy(self):
645 return 'copy'
646
647 def keys(self):
648 return 'keys'
649
650 def items(self):
651 return 'items'
652
653 def values(self):
654 return 'values'
655
656 def __getitem__(self, key):
657 return "getitem=%s" % dict.__getitem__(self, key)
658
659 def get(self, key, default=None):
660 return "get=%s" % dict.get(self, key, 'default=%r' % default)
661
662 custom = customdict({'key': 'value'})
663 view = self.mappingproxy(custom)
664 self.assertTrue('key' in view)
665 self.assertTrue('magic' in view)
666 self.assertFalse('xxx' in view)
667 self.assertEqual(view['key'], 'getitem=value')
668 self.assertRaises(KeyError, view.__getitem__, 'xxx')
669 self.assertEqual(tuple(view), ('iter',))
670 self.assertEqual(len(view), 500)
671 self.assertEqual(view.copy(), 'copy')
672 self.assertEqual(view.get('key'), 'get=value')
673 self.assertEqual(view.get('xxx'), 'get=default=None')
674 self.assertEqual(view.items(), 'items')
675 self.assertEqual(view.keys(), 'keys')
676 self.assertEqual(view.values(), 'values')
677
678 def test_chainmap(self):
679 d1 = {'x': 1}
680 d2 = {'y': 2}
681 mapping = collections.ChainMap(d1, d2)
682 view = self.mappingproxy(mapping)
683 self.assertTrue('x' in view)
684 self.assertTrue('y' in view)
685 self.assertFalse('z' in view)
686 self.assertEqual(view['x'], 1)
687 self.assertEqual(view['y'], 2)
688 self.assertRaises(KeyError, view.__getitem__, 'z')
689 self.assertEqual(tuple(sorted(view)), ('x', 'y'))
690 self.assertEqual(len(view), 2)
691 copy = view.copy()
692 self.assertIsNot(copy, mapping)
693 self.assertIsInstance(copy, collections.ChainMap)
694 self.assertEqual(copy, mapping)
695 self.assertEqual(view.get('x'), 1)
696 self.assertEqual(view.get('y'), 2)
697 self.assertIsNone(view.get('z'))
698 self.assertEqual(tuple(sorted(view.items())), (('x', 1), ('y', 2)))
699 self.assertEqual(tuple(sorted(view.keys())), ('x', 'y'))
700 self.assertEqual(tuple(sorted(view.values())), (1, 2))
701
702 def test_contains(self):
703 view = self.mappingproxy(dict.fromkeys('abc'))
704 self.assertTrue('a' in view)
705 self.assertTrue('b' in view)
706 self.assertTrue('c' in view)
707 self.assertFalse('xxx' in view)
708
709 def test_views(self):
710 mapping = {}
711 view = self.mappingproxy(mapping)
712 keys = view.keys()
713 values = view.values()
714 items = view.items()
715 self.assertEqual(list(keys), [])
716 self.assertEqual(list(values), [])
717 self.assertEqual(list(items), [])
718 mapping['key'] = 'value'
719 self.assertEqual(list(keys), ['key'])
720 self.assertEqual(list(values), ['value'])
721 self.assertEqual(list(items), [('key', 'value')])
722
723 def test_len(self):
724 for expected in range(6):
725 data = dict.fromkeys('abcde'[:expected])
726 self.assertEqual(len(data), expected)
727 view = self.mappingproxy(data)
728 self.assertEqual(len(view), expected)
729
730 def test_iterators(self):
731 keys = ('x', 'y')
732 values = (1, 2)
733 items = tuple(zip(keys, values))
734 view = self.mappingproxy(dict(items))
735 self.assertEqual(set(view), set(keys))
736 self.assertEqual(set(view.keys()), set(keys))
737 self.assertEqual(set(view.values()), set(values))
738 self.assertEqual(set(view.items()), set(items))
739
740 def test_copy(self):
741 original = {'key1': 27, 'key2': 51, 'key3': 93}
742 view = self.mappingproxy(original)
743 copy = view.copy()
744 self.assertEqual(type(copy), dict)
745 self.assertEqual(copy, original)
746 original['key1'] = 70
747 self.assertEqual(view['key1'], 70)
748 self.assertEqual(copy['key1'], 27)
749
750
Nick Coghlan7fc570a2012-05-20 02:34:13 +1000751class ClassCreationTests(unittest.TestCase):
752
753 class Meta(type):
754 def __init__(cls, name, bases, ns, **kw):
755 super().__init__(name, bases, ns)
756 @staticmethod
757 def __new__(mcls, name, bases, ns, **kw):
758 return super().__new__(mcls, name, bases, ns)
759 @classmethod
760 def __prepare__(mcls, name, bases, **kw):
761 ns = super().__prepare__(name, bases)
762 ns["y"] = 1
763 ns.update(kw)
764 return ns
765
766 def test_new_class_basics(self):
767 C = types.new_class("C")
768 self.assertEqual(C.__name__, "C")
769 self.assertEqual(C.__bases__, (object,))
770
771 def test_new_class_subclass(self):
772 C = types.new_class("C", (int,))
773 self.assertTrue(issubclass(C, int))
774
775 def test_new_class_meta(self):
776 Meta = self.Meta
777 settings = {"metaclass": Meta, "z": 2}
778 # We do this twice to make sure the passed in dict isn't mutated
779 for i in range(2):
780 C = types.new_class("C" + str(i), (), settings)
781 self.assertIsInstance(C, Meta)
782 self.assertEqual(C.y, 1)
783 self.assertEqual(C.z, 2)
784
785 def test_new_class_exec_body(self):
786 Meta = self.Meta
787 def func(ns):
788 ns["x"] = 0
789 C = types.new_class("C", (), {"metaclass": Meta, "z": 2}, func)
790 self.assertIsInstance(C, Meta)
791 self.assertEqual(C.x, 0)
792 self.assertEqual(C.y, 1)
793 self.assertEqual(C.z, 2)
794
Benjamin Peterson43f8f4c2012-09-27 18:10:17 -0400795 def test_new_class_metaclass_keywords(self):
Nick Coghlan7fc570a2012-05-20 02:34:13 +1000796 #Test that keywords are passed to the metaclass:
797 def meta_func(name, bases, ns, **kw):
798 return name, bases, ns, kw
799 res = types.new_class("X",
800 (int, object),
801 dict(metaclass=meta_func, x=0))
802 self.assertEqual(res, ("X", (int, object), {}, {"x": 0}))
803
804 def test_new_class_defaults(self):
805 # Test defaults/keywords:
806 C = types.new_class("C", (), {}, None)
807 self.assertEqual(C.__name__, "C")
808 self.assertEqual(C.__bases__, (object,))
809
810 def test_new_class_meta_with_base(self):
811 Meta = self.Meta
812 def func(ns):
813 ns["x"] = 0
814 C = types.new_class(name="C",
815 bases=(int,),
816 kwds=dict(metaclass=Meta, z=2),
817 exec_body=func)
818 self.assertTrue(issubclass(C, int))
819 self.assertIsInstance(C, Meta)
820 self.assertEqual(C.x, 0)
821 self.assertEqual(C.y, 1)
822 self.assertEqual(C.z, 2)
823
824 # Many of the following tests are derived from test_descr.py
825 def test_prepare_class(self):
826 # Basic test of metaclass derivation
827 expected_ns = {}
828 class A(type):
829 def __new__(*args, **kwargs):
830 return type.__new__(*args, **kwargs)
831
832 def __prepare__(*args):
833 return expected_ns
834
835 B = types.new_class("B", (object,))
836 C = types.new_class("C", (object,), {"metaclass": A})
837
838 # The most derived metaclass of D is A rather than type.
839 meta, ns, kwds = types.prepare_class("D", (B, C), {"metaclass": type})
840 self.assertIs(meta, A)
841 self.assertIs(ns, expected_ns)
842 self.assertEqual(len(kwds), 0)
843
844 def test_metaclass_derivation(self):
845 # issue1294232: correct metaclass calculation
846 new_calls = [] # to check the order of __new__ calls
847 class AMeta(type):
848 def __new__(mcls, name, bases, ns):
849 new_calls.append('AMeta')
850 return super().__new__(mcls, name, bases, ns)
851 @classmethod
852 def __prepare__(mcls, name, bases):
853 return {}
854
855 class BMeta(AMeta):
856 def __new__(mcls, name, bases, ns):
857 new_calls.append('BMeta')
858 return super().__new__(mcls, name, bases, ns)
859 @classmethod
860 def __prepare__(mcls, name, bases):
861 ns = super().__prepare__(name, bases)
862 ns['BMeta_was_here'] = True
863 return ns
864
865 A = types.new_class("A", (), {"metaclass": AMeta})
866 self.assertEqual(new_calls, ['AMeta'])
867 new_calls.clear()
868
869 B = types.new_class("B", (), {"metaclass": BMeta})
870 # BMeta.__new__ calls AMeta.__new__ with super:
871 self.assertEqual(new_calls, ['BMeta', 'AMeta'])
872 new_calls.clear()
873
874 C = types.new_class("C", (A, B))
875 # The most derived metaclass is BMeta:
876 self.assertEqual(new_calls, ['BMeta', 'AMeta'])
877 new_calls.clear()
878 # BMeta.__prepare__ should've been called:
879 self.assertIn('BMeta_was_here', C.__dict__)
880
881 # The order of the bases shouldn't matter:
882 C2 = types.new_class("C2", (B, A))
883 self.assertEqual(new_calls, ['BMeta', 'AMeta'])
884 new_calls.clear()
885 self.assertIn('BMeta_was_here', C2.__dict__)
886
887 # Check correct metaclass calculation when a metaclass is declared:
888 D = types.new_class("D", (C,), {"metaclass": type})
889 self.assertEqual(new_calls, ['BMeta', 'AMeta'])
890 new_calls.clear()
891 self.assertIn('BMeta_was_here', D.__dict__)
892
893 E = types.new_class("E", (C,), {"metaclass": AMeta})
894 self.assertEqual(new_calls, ['BMeta', 'AMeta'])
895 new_calls.clear()
896 self.assertIn('BMeta_was_here', E.__dict__)
897
898 def test_metaclass_override_function(self):
899 # Special case: the given metaclass isn't a class,
900 # so there is no metaclass calculation.
901 class A(metaclass=self.Meta):
902 pass
903
904 marker = object()
905 def func(*args, **kwargs):
906 return marker
907
908 X = types.new_class("X", (), {"metaclass": func})
909 Y = types.new_class("Y", (object,), {"metaclass": func})
910 Z = types.new_class("Z", (A,), {"metaclass": func})
911 self.assertIs(marker, X)
912 self.assertIs(marker, Y)
913 self.assertIs(marker, Z)
914
915 def test_metaclass_override_callable(self):
916 # The given metaclass is a class,
917 # but not a descendant of type.
918 new_calls = [] # to check the order of __new__ calls
919 prepare_calls = [] # to track __prepare__ calls
920 class ANotMeta:
921 def __new__(mcls, *args, **kwargs):
922 new_calls.append('ANotMeta')
923 return super().__new__(mcls)
924 @classmethod
925 def __prepare__(mcls, name, bases):
926 prepare_calls.append('ANotMeta')
927 return {}
928
929 class BNotMeta(ANotMeta):
930 def __new__(mcls, *args, **kwargs):
931 new_calls.append('BNotMeta')
932 return super().__new__(mcls)
933 @classmethod
934 def __prepare__(mcls, name, bases):
935 prepare_calls.append('BNotMeta')
936 return super().__prepare__(name, bases)
937
938 A = types.new_class("A", (), {"metaclass": ANotMeta})
939 self.assertIs(ANotMeta, type(A))
940 self.assertEqual(prepare_calls, ['ANotMeta'])
941 prepare_calls.clear()
942 self.assertEqual(new_calls, ['ANotMeta'])
943 new_calls.clear()
944
945 B = types.new_class("B", (), {"metaclass": BNotMeta})
946 self.assertIs(BNotMeta, type(B))
947 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
948 prepare_calls.clear()
949 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
950 new_calls.clear()
951
952 C = types.new_class("C", (A, B))
953 self.assertIs(BNotMeta, type(C))
954 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
955 prepare_calls.clear()
956 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
957 new_calls.clear()
958
959 C2 = types.new_class("C2", (B, A))
960 self.assertIs(BNotMeta, type(C2))
961 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
962 prepare_calls.clear()
963 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
964 new_calls.clear()
965
966 # This is a TypeError, because of a metaclass conflict:
967 # BNotMeta is neither a subclass, nor a superclass of type
968 with self.assertRaises(TypeError):
969 D = types.new_class("D", (C,), {"metaclass": type})
970
971 E = types.new_class("E", (C,), {"metaclass": ANotMeta})
972 self.assertIs(BNotMeta, type(E))
973 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
974 prepare_calls.clear()
975 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
976 new_calls.clear()
977
978 F = types.new_class("F", (object(), C))
979 self.assertIs(BNotMeta, type(F))
980 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
981 prepare_calls.clear()
982 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
983 new_calls.clear()
984
985 F2 = types.new_class("F2", (C, object()))
986 self.assertIs(BNotMeta, type(F2))
987 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
988 prepare_calls.clear()
989 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
990 new_calls.clear()
991
992 # TypeError: BNotMeta is neither a
993 # subclass, nor a superclass of int
994 with self.assertRaises(TypeError):
995 X = types.new_class("X", (C, int()))
996 with self.assertRaises(TypeError):
997 X = types.new_class("X", (int(), C))
998
999
Barry Warsaw409da152012-06-03 16:18:47 -04001000class SimpleNamespaceTests(unittest.TestCase):
1001
1002 def test_constructor(self):
1003 ns1 = types.SimpleNamespace()
1004 ns2 = types.SimpleNamespace(x=1, y=2)
1005 ns3 = types.SimpleNamespace(**dict(x=1, y=2))
1006
1007 with self.assertRaises(TypeError):
1008 types.SimpleNamespace(1, 2, 3)
1009
1010 self.assertEqual(len(ns1.__dict__), 0)
1011 self.assertEqual(vars(ns1), {})
1012 self.assertEqual(len(ns2.__dict__), 2)
1013 self.assertEqual(vars(ns2), {'y': 2, 'x': 1})
1014 self.assertEqual(len(ns3.__dict__), 2)
1015 self.assertEqual(vars(ns3), {'y': 2, 'x': 1})
1016
1017 def test_unbound(self):
1018 ns1 = vars(types.SimpleNamespace())
1019 ns2 = vars(types.SimpleNamespace(x=1, y=2))
1020
1021 self.assertEqual(ns1, {})
1022 self.assertEqual(ns2, {'y': 2, 'x': 1})
1023
1024 def test_underlying_dict(self):
1025 ns1 = types.SimpleNamespace()
1026 ns2 = types.SimpleNamespace(x=1, y=2)
1027 ns3 = types.SimpleNamespace(a=True, b=False)
1028 mapping = ns3.__dict__
1029 del ns3
1030
1031 self.assertEqual(ns1.__dict__, {})
1032 self.assertEqual(ns2.__dict__, {'y': 2, 'x': 1})
1033 self.assertEqual(mapping, dict(a=True, b=False))
1034
1035 def test_attrget(self):
1036 ns = types.SimpleNamespace(x=1, y=2, w=3)
1037
1038 self.assertEqual(ns.x, 1)
1039 self.assertEqual(ns.y, 2)
1040 self.assertEqual(ns.w, 3)
1041 with self.assertRaises(AttributeError):
1042 ns.z
1043
1044 def test_attrset(self):
1045 ns1 = types.SimpleNamespace()
1046 ns2 = types.SimpleNamespace(x=1, y=2, w=3)
1047 ns1.a = 'spam'
1048 ns1.b = 'ham'
1049 ns2.z = 4
1050 ns2.theta = None
1051
1052 self.assertEqual(ns1.__dict__, dict(a='spam', b='ham'))
1053 self.assertEqual(ns2.__dict__, dict(x=1, y=2, w=3, z=4, theta=None))
1054
1055 def test_attrdel(self):
1056 ns1 = types.SimpleNamespace()
1057 ns2 = types.SimpleNamespace(x=1, y=2, w=3)
1058
1059 with self.assertRaises(AttributeError):
1060 del ns1.spam
1061 with self.assertRaises(AttributeError):
1062 del ns2.spam
1063
1064 del ns2.y
1065 self.assertEqual(vars(ns2), dict(w=3, x=1))
1066 ns2.y = 'spam'
1067 self.assertEqual(vars(ns2), dict(w=3, x=1, y='spam'))
1068 del ns2.y
1069 self.assertEqual(vars(ns2), dict(w=3, x=1))
1070
1071 ns1.spam = 5
1072 self.assertEqual(vars(ns1), dict(spam=5))
1073 del ns1.spam
1074 self.assertEqual(vars(ns1), {})
1075
1076 def test_repr(self):
1077 ns1 = types.SimpleNamespace(x=1, y=2, w=3)
1078 ns2 = types.SimpleNamespace()
1079 ns2.x = "spam"
1080 ns2._y = 5
Eric Snowb5c8f922013-02-16 16:32:39 -07001081 name = "namespace"
Barry Warsaw409da152012-06-03 16:18:47 -04001082
Eric Snowb5c8f922013-02-16 16:32:39 -07001083 self.assertEqual(repr(ns1), "{name}(w=3, x=1, y=2)".format(name=name))
1084 self.assertEqual(repr(ns2), "{name}(_y=5, x='spam')".format(name=name))
1085
1086 def test_equal(self):
1087 ns1 = types.SimpleNamespace(x=1)
1088 ns2 = types.SimpleNamespace()
1089 ns2.x = 1
1090
1091 self.assertEqual(types.SimpleNamespace(), types.SimpleNamespace())
1092 self.assertEqual(ns1, ns2)
1093 self.assertNotEqual(ns2, types.SimpleNamespace())
Barry Warsaw409da152012-06-03 16:18:47 -04001094
1095 def test_nested(self):
1096 ns1 = types.SimpleNamespace(a=1, b=2)
1097 ns2 = types.SimpleNamespace()
1098 ns3 = types.SimpleNamespace(x=ns1)
1099 ns2.spam = ns1
1100 ns2.ham = '?'
1101 ns2.spam = ns3
1102
1103 self.assertEqual(vars(ns1), dict(a=1, b=2))
1104 self.assertEqual(vars(ns2), dict(spam=ns3, ham='?'))
1105 self.assertEqual(ns2.spam, ns3)
1106 self.assertEqual(vars(ns3), dict(x=ns1))
1107 self.assertEqual(ns3.x.a, 1)
1108
1109 def test_recursive(self):
1110 ns1 = types.SimpleNamespace(c='cookie')
1111 ns2 = types.SimpleNamespace()
1112 ns3 = types.SimpleNamespace(x=1)
1113 ns1.spam = ns1
1114 ns2.spam = ns3
1115 ns3.spam = ns2
1116
1117 self.assertEqual(ns1.spam, ns1)
1118 self.assertEqual(ns1.spam.spam, ns1)
1119 self.assertEqual(ns1.spam.spam, ns1.spam)
1120 self.assertEqual(ns2.spam, ns3)
1121 self.assertEqual(ns3.spam, ns2)
1122 self.assertEqual(ns2.spam.spam, ns2)
1123
1124 def test_recursive_repr(self):
1125 ns1 = types.SimpleNamespace(c='cookie')
1126 ns2 = types.SimpleNamespace()
1127 ns3 = types.SimpleNamespace(x=1)
1128 ns1.spam = ns1
1129 ns2.spam = ns3
1130 ns3.spam = ns2
Eric Snowb5c8f922013-02-16 16:32:39 -07001131 name = "namespace"
1132 repr1 = "{name}(c='cookie', spam={name}(...))".format(name=name)
1133 repr2 = "{name}(spam={name}(spam={name}(...), x=1))".format(name=name)
Barry Warsaw409da152012-06-03 16:18:47 -04001134
Eric Snowb5c8f922013-02-16 16:32:39 -07001135 self.assertEqual(repr(ns1), repr1)
1136 self.assertEqual(repr(ns2), repr2)
Barry Warsaw409da152012-06-03 16:18:47 -04001137
1138 def test_as_dict(self):
1139 ns = types.SimpleNamespace(spam='spamspamspam')
1140
1141 with self.assertRaises(TypeError):
1142 len(ns)
1143 with self.assertRaises(TypeError):
1144 iter(ns)
1145 with self.assertRaises(TypeError):
1146 'spam' in ns
1147 with self.assertRaises(TypeError):
1148 ns['spam']
1149
Eric Snow547298c2012-10-16 22:35:38 -07001150 def test_subclass(self):
1151 class Spam(types.SimpleNamespace):
1152 pass
1153
1154 spam = Spam(ham=8, eggs=9)
1155
1156 self.assertIs(type(spam), Spam)
1157 self.assertEqual(vars(spam), {'ham': 8, 'eggs': 9})
1158
Eric Snowb5c8f922013-02-16 16:32:39 -07001159 def test_pickle(self):
1160 ns = types.SimpleNamespace(breakfast="spam", lunch="spam")
1161
Eric Snow9d05c8c2013-02-16 18:20:32 -07001162 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1163 pname = "protocol {}".format(protocol)
1164 try:
1165 ns_pickled = pickle.dumps(ns, protocol)
1166 except TypeError as e:
1167 raise TypeError(pname) from e
1168 ns_roundtrip = pickle.loads(ns_pickled)
Eric Snowb5c8f922013-02-16 16:32:39 -07001169
Eric Snow9d05c8c2013-02-16 18:20:32 -07001170 self.assertEqual(ns, ns_roundtrip, pname)
Eric Snowb5c8f922013-02-16 16:32:39 -07001171
Barry Warsaw409da152012-06-03 16:18:47 -04001172
Thomas Wouters89f507f2006-12-13 04:49:30 +00001173def test_main():
Barry Warsaw409da152012-06-03 16:18:47 -04001174 run_unittest(TypesTests, MappingProxyTests, ClassCreationTests,
1175 SimpleNamespaceTests)
Neil Schemenauereff72442002-03-24 01:24:54 +00001176
Thomas Wouters89f507f2006-12-13 04:49:30 +00001177if __name__ == '__main__':
1178 test_main()