blob: 8cdecb03d3e5271bae4513646af25452d9795f55 [file] [log] [blame]
Guido van Rossum85f18201992-11-27 22:53:50 +00001# Python test set -- part 6, built-in types
2
Zachary Ware38c707e2015-04-13 15:00:43 -05003from test.support import 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")
Eric V. Smitha12572f2014-04-15 22:37:55 -0400346 # can't have '#' with 'c'
347 self.assertRaises(ValueError, 3 .__format__, "#c")
Christian Heimes7131fd92008-02-19 14:21:46 +0000348
349 # ensure that only int and float type specifiers work
350 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
351 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
352 if not format_spec in 'bcdoxXeEfFgGn%':
353 self.assertRaises(ValueError, 0 .__format__, format_spec)
354 self.assertRaises(ValueError, 1 .__format__, format_spec)
355 self.assertRaises(ValueError, (-1) .__format__, format_spec)
356
357 # ensure that float type specifiers work; format converts
358 # the int to a float
Eric Smith5807c412008-05-11 21:00:57 +0000359 for format_spec in 'eEfFgG%':
Christian Heimes7131fd92008-02-19 14:21:46 +0000360 for value in [0, 1, -1, 100, -100, 1234567890, -1234567890]:
361 self.assertEqual(value.__format__(format_spec),
362 float(value).__format__(format_spec))
363
Eric Smithabb28c62010-02-23 00:22:24 +0000364 # Issue 6902
365 test(123456, "0<20", '12345600000000000000')
366 test(123456, "1<20", '12345611111111111111')
367 test(123456, "*<20", '123456**************')
368 test(123456, "0>20", '00000000000000123456')
369 test(123456, "1>20", '11111111111111123456')
370 test(123456, "*>20", '**************123456')
371 test(123456, "0=20", '00000000000000123456')
372 test(123456, "1=20", '11111111111111123456')
373 test(123456, "*=20", '**************123456')
374
Eric Smithb2c7af82008-04-30 02:12:09 +0000375 @run_with_locale('LC_NUMERIC', 'en_US.UTF8')
376 def test_float__format__locale(self):
377 # test locale support for __format__ code 'n'
378
379 for i in range(-10, 10):
380 x = 1234567890.0 * (10.0 ** i)
381 self.assertEqual(locale.format('%g', x, grouping=True), format(x, 'n'))
382 self.assertEqual(locale.format('%.10g', x, grouping=True), format(x, '.10n'))
383
Eric Smith5807c412008-05-11 21:00:57 +0000384 @run_with_locale('LC_NUMERIC', 'en_US.UTF8')
385 def test_int__format__locale(self):
386 # test locale support for __format__ code 'n' for integers
387
388 x = 123456789012345678901234567890
389 for i in range(0, 30):
390 self.assertEqual(locale.format('%d', x, grouping=True), format(x, 'n'))
391
392 # move to the next integer to test
393 x = x // 10
394
Eric Smithb151a452008-06-24 11:21:04 +0000395 rfmt = ">20n"
396 lfmt = "<20n"
397 cfmt = "^20n"
398 for x in (1234, 12345, 123456, 1234567, 12345678, 123456789, 1234567890, 12345678900):
399 self.assertEqual(len(format(0, rfmt)), len(format(x, rfmt)))
400 self.assertEqual(len(format(0, lfmt)), len(format(x, lfmt)))
401 self.assertEqual(len(format(0, cfmt)), len(format(x, cfmt)))
402
Christian Heimes7131fd92008-02-19 14:21:46 +0000403 def test_float__format__(self):
Christian Heimes7131fd92008-02-19 14:21:46 +0000404 def test(f, format_spec, result):
Christian Heimes7131fd92008-02-19 14:21:46 +0000405 self.assertEqual(f.__format__(format_spec), result)
Eric Smith984bb582010-11-25 16:08:06 +0000406 self.assertEqual(format(f, format_spec), result)
Christian Heimes7131fd92008-02-19 14:21:46 +0000407
408 test(0.0, 'f', '0.000000')
409
410 # the default is 'g', except for empty format spec
411 test(0.0, '', '0.0')
412 test(0.01, '', '0.01')
413 test(0.01, 'g', '0.01')
414
Eric Smith2ad79e82008-07-19 00:33:23 +0000415 # test for issue 3411
416 test(1.23, '1', '1.23')
417 test(-1.23, '1', '-1.23')
418 test(1.23, '1g', '1.23')
419 test(-1.23, '1g', '-1.23')
420
Christian Heimes7131fd92008-02-19 14:21:46 +0000421 test( 1.0, ' g', ' 1')
422 test(-1.0, ' g', '-1')
423 test( 1.0, '+g', '+1')
424 test(-1.0, '+g', '-1')
425 test(1.1234e200, 'g', '1.1234e+200')
426 test(1.1234e200, 'G', '1.1234E+200')
427
428
429 test(1.0, 'f', '1.000000')
430
431 test(-1.0, 'f', '-1.000000')
432
433 test( 1.0, ' f', ' 1.000000')
434 test(-1.0, ' f', '-1.000000')
435 test( 1.0, '+f', '+1.000000')
436 test(-1.0, '+f', '-1.000000')
Mark Dickinson33841c32009-05-01 15:37:04 +0000437
438 # Python versions <= 3.0 switched from 'f' to 'g' formatting for
439 # values larger than 1e50. No longer.
440 f = 1.1234e90
441 for fmt in 'f', 'F':
442 # don't do a direct equality check, since on some
443 # platforms only the first few digits of dtoa
444 # will be reliable
445 result = f.__format__(fmt)
446 self.assertEqual(len(result), 98)
447 self.assertEqual(result[-7], '.')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000448 self.assertIn(result[:12], ('112340000000', '112339999999'))
Mark Dickinson33841c32009-05-01 15:37:04 +0000449 f = 1.1234e200
450 for fmt in 'f', 'F':
451 result = f.__format__(fmt)
452 self.assertEqual(len(result), 208)
453 self.assertEqual(result[-7], '.')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000454 self.assertIn(result[:12], ('112340000000', '112339999999'))
Mark Dickinson33841c32009-05-01 15:37:04 +0000455
Christian Heimes7131fd92008-02-19 14:21:46 +0000456
Christian Heimesc3f30c42008-02-22 16:37:40 +0000457 test( 1.0, 'e', '1.000000e+00')
458 test(-1.0, 'e', '-1.000000e+00')
459 test( 1.0, 'E', '1.000000E+00')
460 test(-1.0, 'E', '-1.000000E+00')
461 test(1.1234e20, 'e', '1.123400e+20')
462 test(1.1234e20, 'E', '1.123400E+20')
Christian Heimes7131fd92008-02-19 14:21:46 +0000463
Christian Heimesb186d002008-03-18 15:15:01 +0000464 # No format code means use g, but must have a decimal
465 # and a number after the decimal. This is tricky, because
466 # a totaly empty format specifier means something else.
467 # So, just use a sign flag
468 test(1e200, '+g', '+1e+200')
Eric Smith0923d1d2009-04-16 20:16:10 +0000469 test(1e200, '+', '+1e+200')
470
Christian Heimesb186d002008-03-18 15:15:01 +0000471 test(1.1e200, '+g', '+1.1e+200')
472 test(1.1e200, '+', '+1.1e+200')
473
Eric Smith0923d1d2009-04-16 20:16:10 +0000474 # 0 padding
475 test(1234., '010f', '1234.000000')
476 test(1234., '011f', '1234.000000')
477 test(1234., '012f', '01234.000000')
478 test(-1234., '011f', '-1234.000000')
479 test(-1234., '012f', '-1234.000000')
480 test(-1234., '013f', '-01234.000000')
481 test(-1234.12341234, '013f', '-01234.123412')
482 test(-123456.12341234, '011.2f', '-0123456.12')
483
Eric Smith937491d2009-04-22 17:04:27 +0000484 # issue 5782, commas with no specifier type
485 test(1.2, '010,.2', '0,000,001.2')
486
Eric Smith0923d1d2009-04-16 20:16:10 +0000487 # 0 padding with commas
488 test(1234., '011,f', '1,234.000000')
489 test(1234., '012,f', '1,234.000000')
490 test(1234., '013,f', '01,234.000000')
491 test(-1234., '012,f', '-1,234.000000')
492 test(-1234., '013,f', '-1,234.000000')
493 test(-1234., '014,f', '-01,234.000000')
494 test(-12345., '015,f', '-012,345.000000')
495 test(-123456., '016,f', '-0,123,456.000000')
496 test(-123456., '017,f', '-0,123,456.000000')
497 test(-123456.12341234, '017,f', '-0,123,456.123412')
498 test(-123456.12341234, '013,.2f', '-0,123,456.12')
499
Christian Heimes7131fd92008-02-19 14:21:46 +0000500 # % formatting
501 test(-1.0, '%', '-100.000000%')
502
503 # format spec must be string
504 self.assertRaises(TypeError, 3.0.__format__, None)
505 self.assertRaises(TypeError, 3.0.__format__, 0)
506
507 # other format specifiers shouldn't work on floats,
508 # in particular int specifiers
509 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
510 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
511 if not format_spec in 'eEfFgGn%':
512 self.assertRaises(ValueError, format, 0.0, format_spec)
513 self.assertRaises(ValueError, format, 1.0, format_spec)
514 self.assertRaises(ValueError, format, -1.0, format_spec)
515 self.assertRaises(ValueError, format, 1e100, format_spec)
516 self.assertRaises(ValueError, format, -1e100, format_spec)
517 self.assertRaises(ValueError, format, 1e-100, format_spec)
518 self.assertRaises(ValueError, format, -1e-100, format_spec)
519
Eric Smith984bb582010-11-25 16:08:06 +0000520 # Alternate float formatting
521 test(1.0, '.0e', '1e+00')
522 test(1.0, '#.0e', '1.e+00')
523 test(1.0, '.0f', '1')
524 test(1.0, '#.0f', '1.')
525 test(1.1, 'g', '1.1')
526 test(1.1, '#g', '1.10000')
527 test(1.0, '.0%', '100%')
528 test(1.0, '#.0%', '100.%')
529
530 # Issue 7094: Alternate formatting (specified by #)
531 test(1.0, '0e', '1.000000e+00')
532 test(1.0, '#0e', '1.000000e+00')
533 test(1.0, '0f', '1.000000' )
534 test(1.0, '#0f', '1.000000')
535 test(1.0, '.1e', '1.0e+00')
536 test(1.0, '#.1e', '1.0e+00')
537 test(1.0, '.1f', '1.0')
538 test(1.0, '#.1f', '1.0')
539 test(1.0, '.1%', '100.0%')
540 test(1.0, '#.1%', '100.0%')
Eric Smithb1ebcc62008-07-15 13:02:41 +0000541
Eric Smithabb28c62010-02-23 00:22:24 +0000542 # Issue 6902
543 test(12345.6, "0<20", '12345.60000000000000')
544 test(12345.6, "1<20", '12345.61111111111111')
545 test(12345.6, "*<20", '12345.6*************')
546 test(12345.6, "0>20", '000000000000012345.6')
547 test(12345.6, "1>20", '111111111111112345.6')
548 test(12345.6, "*>20", '*************12345.6')
549 test(12345.6, "0=20", '000000000000012345.6')
550 test(12345.6, "1=20", '111111111111112345.6')
551 test(12345.6, "*=20", '*************12345.6')
552
Eric Smith0923d1d2009-04-16 20:16:10 +0000553 def test_format_spec_errors(self):
554 # int, float, and string all share the same format spec
555 # mini-language parser.
556
557 # Check that we can't ask for too many digits. This is
558 # probably a CPython specific test. It tries to put the width
559 # into a C long.
560 self.assertRaises(ValueError, format, 0, '1'*10000 + 'd')
561
562 # Similar with the precision.
563 self.assertRaises(ValueError, format, 0, '.' + '1'*10000 + 'd')
564
565 # And may as well test both.
566 self.assertRaises(ValueError, format, 0, '1'*1000 + '.' + '1'*10000 + 'd')
567
568 # Make sure commas aren't allowed with various type codes
569 for code in 'xXobns':
570 self.assertRaises(ValueError, format, 0, ',' + code)
Christian Heimes7131fd92008-02-19 14:21:46 +0000571
Benjamin Peterson0e102062010-08-25 23:13:17 +0000572 def test_internal_sizes(self):
573 self.assertGreater(object.__basicsize__, 0)
574 self.assertGreater(tuple.__itemsize__, 0)
575
576
Victor Stinner0db176f2012-04-16 00:16:30 +0200577class MappingProxyTests(unittest.TestCase):
578 mappingproxy = types.MappingProxyType
579
580 def test_constructor(self):
581 class userdict(dict):
582 pass
583
584 mapping = {'x': 1, 'y': 2}
585 self.assertEqual(self.mappingproxy(mapping), mapping)
586 mapping = userdict(x=1, y=2)
587 self.assertEqual(self.mappingproxy(mapping), mapping)
588 mapping = collections.ChainMap({'x': 1}, {'y': 2})
589 self.assertEqual(self.mappingproxy(mapping), mapping)
590
591 self.assertRaises(TypeError, self.mappingproxy, 10)
592 self.assertRaises(TypeError, self.mappingproxy, ("a", "tuple"))
593 self.assertRaises(TypeError, self.mappingproxy, ["a", "list"])
594
595 def test_methods(self):
596 attrs = set(dir(self.mappingproxy({}))) - set(dir(object()))
597 self.assertEqual(attrs, {
598 '__contains__',
599 '__getitem__',
600 '__iter__',
601 '__len__',
602 'copy',
603 'get',
604 'items',
605 'keys',
606 'values',
607 })
608
609 def test_get(self):
610 view = self.mappingproxy({'a': 'A', 'b': 'B'})
611 self.assertEqual(view['a'], 'A')
612 self.assertEqual(view['b'], 'B')
613 self.assertRaises(KeyError, view.__getitem__, 'xxx')
614 self.assertEqual(view.get('a'), 'A')
615 self.assertIsNone(view.get('xxx'))
616 self.assertEqual(view.get('xxx', 42), 42)
617
618 def test_missing(self):
619 class dictmissing(dict):
620 def __missing__(self, key):
621 return "missing=%s" % key
622
623 view = self.mappingproxy(dictmissing(x=1))
624 self.assertEqual(view['x'], 1)
625 self.assertEqual(view['y'], 'missing=y')
626 self.assertEqual(view.get('x'), 1)
627 self.assertEqual(view.get('y'), None)
628 self.assertEqual(view.get('y', 42), 42)
629 self.assertTrue('x' in view)
630 self.assertFalse('y' in view)
631
632 def test_customdict(self):
633 class customdict(dict):
634 def __contains__(self, key):
635 if key == 'magic':
636 return True
637 else:
638 return dict.__contains__(self, key)
639
640 def __iter__(self):
641 return iter(('iter',))
642
643 def __len__(self):
644 return 500
645
646 def copy(self):
647 return 'copy'
648
649 def keys(self):
650 return 'keys'
651
652 def items(self):
653 return 'items'
654
655 def values(self):
656 return 'values'
657
658 def __getitem__(self, key):
659 return "getitem=%s" % dict.__getitem__(self, key)
660
661 def get(self, key, default=None):
662 return "get=%s" % dict.get(self, key, 'default=%r' % default)
663
664 custom = customdict({'key': 'value'})
665 view = self.mappingproxy(custom)
666 self.assertTrue('key' in view)
667 self.assertTrue('magic' in view)
668 self.assertFalse('xxx' in view)
669 self.assertEqual(view['key'], 'getitem=value')
670 self.assertRaises(KeyError, view.__getitem__, 'xxx')
671 self.assertEqual(tuple(view), ('iter',))
672 self.assertEqual(len(view), 500)
673 self.assertEqual(view.copy(), 'copy')
674 self.assertEqual(view.get('key'), 'get=value')
675 self.assertEqual(view.get('xxx'), 'get=default=None')
676 self.assertEqual(view.items(), 'items')
677 self.assertEqual(view.keys(), 'keys')
678 self.assertEqual(view.values(), 'values')
679
680 def test_chainmap(self):
681 d1 = {'x': 1}
682 d2 = {'y': 2}
683 mapping = collections.ChainMap(d1, d2)
684 view = self.mappingproxy(mapping)
685 self.assertTrue('x' in view)
686 self.assertTrue('y' in view)
687 self.assertFalse('z' in view)
688 self.assertEqual(view['x'], 1)
689 self.assertEqual(view['y'], 2)
690 self.assertRaises(KeyError, view.__getitem__, 'z')
691 self.assertEqual(tuple(sorted(view)), ('x', 'y'))
692 self.assertEqual(len(view), 2)
693 copy = view.copy()
694 self.assertIsNot(copy, mapping)
695 self.assertIsInstance(copy, collections.ChainMap)
696 self.assertEqual(copy, mapping)
697 self.assertEqual(view.get('x'), 1)
698 self.assertEqual(view.get('y'), 2)
699 self.assertIsNone(view.get('z'))
700 self.assertEqual(tuple(sorted(view.items())), (('x', 1), ('y', 2)))
701 self.assertEqual(tuple(sorted(view.keys())), ('x', 'y'))
702 self.assertEqual(tuple(sorted(view.values())), (1, 2))
703
704 def test_contains(self):
705 view = self.mappingproxy(dict.fromkeys('abc'))
706 self.assertTrue('a' in view)
707 self.assertTrue('b' in view)
708 self.assertTrue('c' in view)
709 self.assertFalse('xxx' in view)
710
711 def test_views(self):
712 mapping = {}
713 view = self.mappingproxy(mapping)
714 keys = view.keys()
715 values = view.values()
716 items = view.items()
717 self.assertEqual(list(keys), [])
718 self.assertEqual(list(values), [])
719 self.assertEqual(list(items), [])
720 mapping['key'] = 'value'
721 self.assertEqual(list(keys), ['key'])
722 self.assertEqual(list(values), ['value'])
723 self.assertEqual(list(items), [('key', 'value')])
724
725 def test_len(self):
726 for expected in range(6):
727 data = dict.fromkeys('abcde'[:expected])
728 self.assertEqual(len(data), expected)
729 view = self.mappingproxy(data)
730 self.assertEqual(len(view), expected)
731
732 def test_iterators(self):
733 keys = ('x', 'y')
734 values = (1, 2)
735 items = tuple(zip(keys, values))
736 view = self.mappingproxy(dict(items))
737 self.assertEqual(set(view), set(keys))
738 self.assertEqual(set(view.keys()), set(keys))
739 self.assertEqual(set(view.values()), set(values))
740 self.assertEqual(set(view.items()), set(items))
741
742 def test_copy(self):
743 original = {'key1': 27, 'key2': 51, 'key3': 93}
744 view = self.mappingproxy(original)
745 copy = view.copy()
746 self.assertEqual(type(copy), dict)
747 self.assertEqual(copy, original)
748 original['key1'] = 70
749 self.assertEqual(view['key1'], 70)
750 self.assertEqual(copy['key1'], 27)
751
752
Nick Coghlan7fc570a2012-05-20 02:34:13 +1000753class ClassCreationTests(unittest.TestCase):
754
755 class Meta(type):
756 def __init__(cls, name, bases, ns, **kw):
757 super().__init__(name, bases, ns)
758 @staticmethod
759 def __new__(mcls, name, bases, ns, **kw):
760 return super().__new__(mcls, name, bases, ns)
761 @classmethod
762 def __prepare__(mcls, name, bases, **kw):
763 ns = super().__prepare__(name, bases)
764 ns["y"] = 1
765 ns.update(kw)
766 return ns
767
768 def test_new_class_basics(self):
769 C = types.new_class("C")
770 self.assertEqual(C.__name__, "C")
771 self.assertEqual(C.__bases__, (object,))
772
773 def test_new_class_subclass(self):
774 C = types.new_class("C", (int,))
775 self.assertTrue(issubclass(C, int))
776
777 def test_new_class_meta(self):
778 Meta = self.Meta
779 settings = {"metaclass": Meta, "z": 2}
780 # We do this twice to make sure the passed in dict isn't mutated
781 for i in range(2):
782 C = types.new_class("C" + str(i), (), settings)
783 self.assertIsInstance(C, Meta)
784 self.assertEqual(C.y, 1)
785 self.assertEqual(C.z, 2)
786
787 def test_new_class_exec_body(self):
788 Meta = self.Meta
789 def func(ns):
790 ns["x"] = 0
791 C = types.new_class("C", (), {"metaclass": Meta, "z": 2}, func)
792 self.assertIsInstance(C, Meta)
793 self.assertEqual(C.x, 0)
794 self.assertEqual(C.y, 1)
795 self.assertEqual(C.z, 2)
796
Benjamin Peterson43f8f4c2012-09-27 18:10:17 -0400797 def test_new_class_metaclass_keywords(self):
Nick Coghlan7fc570a2012-05-20 02:34:13 +1000798 #Test that keywords are passed to the metaclass:
799 def meta_func(name, bases, ns, **kw):
800 return name, bases, ns, kw
801 res = types.new_class("X",
802 (int, object),
803 dict(metaclass=meta_func, x=0))
804 self.assertEqual(res, ("X", (int, object), {}, {"x": 0}))
805
806 def test_new_class_defaults(self):
807 # Test defaults/keywords:
808 C = types.new_class("C", (), {}, None)
809 self.assertEqual(C.__name__, "C")
810 self.assertEqual(C.__bases__, (object,))
811
812 def test_new_class_meta_with_base(self):
813 Meta = self.Meta
814 def func(ns):
815 ns["x"] = 0
816 C = types.new_class(name="C",
817 bases=(int,),
818 kwds=dict(metaclass=Meta, z=2),
819 exec_body=func)
820 self.assertTrue(issubclass(C, int))
821 self.assertIsInstance(C, Meta)
822 self.assertEqual(C.x, 0)
823 self.assertEqual(C.y, 1)
824 self.assertEqual(C.z, 2)
825
826 # Many of the following tests are derived from test_descr.py
827 def test_prepare_class(self):
828 # Basic test of metaclass derivation
829 expected_ns = {}
830 class A(type):
831 def __new__(*args, **kwargs):
832 return type.__new__(*args, **kwargs)
833
834 def __prepare__(*args):
835 return expected_ns
836
837 B = types.new_class("B", (object,))
838 C = types.new_class("C", (object,), {"metaclass": A})
839
840 # The most derived metaclass of D is A rather than type.
841 meta, ns, kwds = types.prepare_class("D", (B, C), {"metaclass": type})
842 self.assertIs(meta, A)
843 self.assertIs(ns, expected_ns)
844 self.assertEqual(len(kwds), 0)
845
846 def test_metaclass_derivation(self):
847 # issue1294232: correct metaclass calculation
848 new_calls = [] # to check the order of __new__ calls
849 class AMeta(type):
850 def __new__(mcls, name, bases, ns):
851 new_calls.append('AMeta')
852 return super().__new__(mcls, name, bases, ns)
853 @classmethod
854 def __prepare__(mcls, name, bases):
855 return {}
856
857 class BMeta(AMeta):
858 def __new__(mcls, name, bases, ns):
859 new_calls.append('BMeta')
860 return super().__new__(mcls, name, bases, ns)
861 @classmethod
862 def __prepare__(mcls, name, bases):
863 ns = super().__prepare__(name, bases)
864 ns['BMeta_was_here'] = True
865 return ns
866
867 A = types.new_class("A", (), {"metaclass": AMeta})
868 self.assertEqual(new_calls, ['AMeta'])
869 new_calls.clear()
870
871 B = types.new_class("B", (), {"metaclass": BMeta})
872 # BMeta.__new__ calls AMeta.__new__ with super:
873 self.assertEqual(new_calls, ['BMeta', 'AMeta'])
874 new_calls.clear()
875
876 C = types.new_class("C", (A, B))
877 # The most derived metaclass is BMeta:
878 self.assertEqual(new_calls, ['BMeta', 'AMeta'])
879 new_calls.clear()
880 # BMeta.__prepare__ should've been called:
881 self.assertIn('BMeta_was_here', C.__dict__)
882
883 # The order of the bases shouldn't matter:
884 C2 = types.new_class("C2", (B, A))
885 self.assertEqual(new_calls, ['BMeta', 'AMeta'])
886 new_calls.clear()
887 self.assertIn('BMeta_was_here', C2.__dict__)
888
889 # Check correct metaclass calculation when a metaclass is declared:
890 D = types.new_class("D", (C,), {"metaclass": type})
891 self.assertEqual(new_calls, ['BMeta', 'AMeta'])
892 new_calls.clear()
893 self.assertIn('BMeta_was_here', D.__dict__)
894
895 E = types.new_class("E", (C,), {"metaclass": AMeta})
896 self.assertEqual(new_calls, ['BMeta', 'AMeta'])
897 new_calls.clear()
898 self.assertIn('BMeta_was_here', E.__dict__)
899
900 def test_metaclass_override_function(self):
901 # Special case: the given metaclass isn't a class,
902 # so there is no metaclass calculation.
903 class A(metaclass=self.Meta):
904 pass
905
906 marker = object()
907 def func(*args, **kwargs):
908 return marker
909
910 X = types.new_class("X", (), {"metaclass": func})
911 Y = types.new_class("Y", (object,), {"metaclass": func})
912 Z = types.new_class("Z", (A,), {"metaclass": func})
913 self.assertIs(marker, X)
914 self.assertIs(marker, Y)
915 self.assertIs(marker, Z)
916
917 def test_metaclass_override_callable(self):
918 # The given metaclass is a class,
919 # but not a descendant of type.
920 new_calls = [] # to check the order of __new__ calls
921 prepare_calls = [] # to track __prepare__ calls
922 class ANotMeta:
923 def __new__(mcls, *args, **kwargs):
924 new_calls.append('ANotMeta')
925 return super().__new__(mcls)
926 @classmethod
927 def __prepare__(mcls, name, bases):
928 prepare_calls.append('ANotMeta')
929 return {}
930
931 class BNotMeta(ANotMeta):
932 def __new__(mcls, *args, **kwargs):
933 new_calls.append('BNotMeta')
934 return super().__new__(mcls)
935 @classmethod
936 def __prepare__(mcls, name, bases):
937 prepare_calls.append('BNotMeta')
938 return super().__prepare__(name, bases)
939
940 A = types.new_class("A", (), {"metaclass": ANotMeta})
941 self.assertIs(ANotMeta, type(A))
942 self.assertEqual(prepare_calls, ['ANotMeta'])
943 prepare_calls.clear()
944 self.assertEqual(new_calls, ['ANotMeta'])
945 new_calls.clear()
946
947 B = types.new_class("B", (), {"metaclass": BNotMeta})
948 self.assertIs(BNotMeta, type(B))
949 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
950 prepare_calls.clear()
951 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
952 new_calls.clear()
953
954 C = types.new_class("C", (A, B))
955 self.assertIs(BNotMeta, type(C))
956 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
957 prepare_calls.clear()
958 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
959 new_calls.clear()
960
961 C2 = types.new_class("C2", (B, A))
962 self.assertIs(BNotMeta, type(C2))
963 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
964 prepare_calls.clear()
965 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
966 new_calls.clear()
967
968 # This is a TypeError, because of a metaclass conflict:
969 # BNotMeta is neither a subclass, nor a superclass of type
970 with self.assertRaises(TypeError):
971 D = types.new_class("D", (C,), {"metaclass": type})
972
973 E = types.new_class("E", (C,), {"metaclass": ANotMeta})
974 self.assertIs(BNotMeta, type(E))
975 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
976 prepare_calls.clear()
977 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
978 new_calls.clear()
979
980 F = types.new_class("F", (object(), C))
981 self.assertIs(BNotMeta, type(F))
982 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
983 prepare_calls.clear()
984 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
985 new_calls.clear()
986
987 F2 = types.new_class("F2", (C, object()))
988 self.assertIs(BNotMeta, type(F2))
989 self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
990 prepare_calls.clear()
991 self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
992 new_calls.clear()
993
994 # TypeError: BNotMeta is neither a
995 # subclass, nor a superclass of int
996 with self.assertRaises(TypeError):
997 X = types.new_class("X", (C, int()))
998 with self.assertRaises(TypeError):
999 X = types.new_class("X", (int(), C))
1000
1001
Barry Warsaw409da152012-06-03 16:18:47 -04001002class SimpleNamespaceTests(unittest.TestCase):
1003
1004 def test_constructor(self):
1005 ns1 = types.SimpleNamespace()
1006 ns2 = types.SimpleNamespace(x=1, y=2)
1007 ns3 = types.SimpleNamespace(**dict(x=1, y=2))
1008
1009 with self.assertRaises(TypeError):
1010 types.SimpleNamespace(1, 2, 3)
1011
1012 self.assertEqual(len(ns1.__dict__), 0)
1013 self.assertEqual(vars(ns1), {})
1014 self.assertEqual(len(ns2.__dict__), 2)
1015 self.assertEqual(vars(ns2), {'y': 2, 'x': 1})
1016 self.assertEqual(len(ns3.__dict__), 2)
1017 self.assertEqual(vars(ns3), {'y': 2, 'x': 1})
1018
1019 def test_unbound(self):
1020 ns1 = vars(types.SimpleNamespace())
1021 ns2 = vars(types.SimpleNamespace(x=1, y=2))
1022
1023 self.assertEqual(ns1, {})
1024 self.assertEqual(ns2, {'y': 2, 'x': 1})
1025
1026 def test_underlying_dict(self):
1027 ns1 = types.SimpleNamespace()
1028 ns2 = types.SimpleNamespace(x=1, y=2)
1029 ns3 = types.SimpleNamespace(a=True, b=False)
1030 mapping = ns3.__dict__
1031 del ns3
1032
1033 self.assertEqual(ns1.__dict__, {})
1034 self.assertEqual(ns2.__dict__, {'y': 2, 'x': 1})
1035 self.assertEqual(mapping, dict(a=True, b=False))
1036
1037 def test_attrget(self):
1038 ns = types.SimpleNamespace(x=1, y=2, w=3)
1039
1040 self.assertEqual(ns.x, 1)
1041 self.assertEqual(ns.y, 2)
1042 self.assertEqual(ns.w, 3)
1043 with self.assertRaises(AttributeError):
1044 ns.z
1045
1046 def test_attrset(self):
1047 ns1 = types.SimpleNamespace()
1048 ns2 = types.SimpleNamespace(x=1, y=2, w=3)
1049 ns1.a = 'spam'
1050 ns1.b = 'ham'
1051 ns2.z = 4
1052 ns2.theta = None
1053
1054 self.assertEqual(ns1.__dict__, dict(a='spam', b='ham'))
1055 self.assertEqual(ns2.__dict__, dict(x=1, y=2, w=3, z=4, theta=None))
1056
1057 def test_attrdel(self):
1058 ns1 = types.SimpleNamespace()
1059 ns2 = types.SimpleNamespace(x=1, y=2, w=3)
1060
1061 with self.assertRaises(AttributeError):
1062 del ns1.spam
1063 with self.assertRaises(AttributeError):
1064 del ns2.spam
1065
1066 del ns2.y
1067 self.assertEqual(vars(ns2), dict(w=3, x=1))
1068 ns2.y = 'spam'
1069 self.assertEqual(vars(ns2), dict(w=3, x=1, y='spam'))
1070 del ns2.y
1071 self.assertEqual(vars(ns2), dict(w=3, x=1))
1072
1073 ns1.spam = 5
1074 self.assertEqual(vars(ns1), dict(spam=5))
1075 del ns1.spam
1076 self.assertEqual(vars(ns1), {})
1077
1078 def test_repr(self):
1079 ns1 = types.SimpleNamespace(x=1, y=2, w=3)
1080 ns2 = types.SimpleNamespace()
1081 ns2.x = "spam"
1082 ns2._y = 5
Eric Snowb5c8f922013-02-16 16:32:39 -07001083 name = "namespace"
Barry Warsaw409da152012-06-03 16:18:47 -04001084
Eric Snowb5c8f922013-02-16 16:32:39 -07001085 self.assertEqual(repr(ns1), "{name}(w=3, x=1, y=2)".format(name=name))
1086 self.assertEqual(repr(ns2), "{name}(_y=5, x='spam')".format(name=name))
1087
1088 def test_equal(self):
1089 ns1 = types.SimpleNamespace(x=1)
1090 ns2 = types.SimpleNamespace()
1091 ns2.x = 1
1092
1093 self.assertEqual(types.SimpleNamespace(), types.SimpleNamespace())
1094 self.assertEqual(ns1, ns2)
1095 self.assertNotEqual(ns2, types.SimpleNamespace())
Barry Warsaw409da152012-06-03 16:18:47 -04001096
1097 def test_nested(self):
1098 ns1 = types.SimpleNamespace(a=1, b=2)
1099 ns2 = types.SimpleNamespace()
1100 ns3 = types.SimpleNamespace(x=ns1)
1101 ns2.spam = ns1
1102 ns2.ham = '?'
1103 ns2.spam = ns3
1104
1105 self.assertEqual(vars(ns1), dict(a=1, b=2))
1106 self.assertEqual(vars(ns2), dict(spam=ns3, ham='?'))
1107 self.assertEqual(ns2.spam, ns3)
1108 self.assertEqual(vars(ns3), dict(x=ns1))
1109 self.assertEqual(ns3.x.a, 1)
1110
1111 def test_recursive(self):
1112 ns1 = types.SimpleNamespace(c='cookie')
1113 ns2 = types.SimpleNamespace()
1114 ns3 = types.SimpleNamespace(x=1)
1115 ns1.spam = ns1
1116 ns2.spam = ns3
1117 ns3.spam = ns2
1118
1119 self.assertEqual(ns1.spam, ns1)
1120 self.assertEqual(ns1.spam.spam, ns1)
1121 self.assertEqual(ns1.spam.spam, ns1.spam)
1122 self.assertEqual(ns2.spam, ns3)
1123 self.assertEqual(ns3.spam, ns2)
1124 self.assertEqual(ns2.spam.spam, ns2)
1125
1126 def test_recursive_repr(self):
1127 ns1 = types.SimpleNamespace(c='cookie')
1128 ns2 = types.SimpleNamespace()
1129 ns3 = types.SimpleNamespace(x=1)
1130 ns1.spam = ns1
1131 ns2.spam = ns3
1132 ns3.spam = ns2
Eric Snowb5c8f922013-02-16 16:32:39 -07001133 name = "namespace"
1134 repr1 = "{name}(c='cookie', spam={name}(...))".format(name=name)
1135 repr2 = "{name}(spam={name}(spam={name}(...), x=1))".format(name=name)
Barry Warsaw409da152012-06-03 16:18:47 -04001136
Eric Snowb5c8f922013-02-16 16:32:39 -07001137 self.assertEqual(repr(ns1), repr1)
1138 self.assertEqual(repr(ns2), repr2)
Barry Warsaw409da152012-06-03 16:18:47 -04001139
1140 def test_as_dict(self):
1141 ns = types.SimpleNamespace(spam='spamspamspam')
1142
1143 with self.assertRaises(TypeError):
1144 len(ns)
1145 with self.assertRaises(TypeError):
1146 iter(ns)
1147 with self.assertRaises(TypeError):
1148 'spam' in ns
1149 with self.assertRaises(TypeError):
1150 ns['spam']
1151
Eric Snow547298c2012-10-16 22:35:38 -07001152 def test_subclass(self):
1153 class Spam(types.SimpleNamespace):
1154 pass
1155
1156 spam = Spam(ham=8, eggs=9)
1157
1158 self.assertIs(type(spam), Spam)
1159 self.assertEqual(vars(spam), {'ham': 8, 'eggs': 9})
1160
Eric Snowb5c8f922013-02-16 16:32:39 -07001161 def test_pickle(self):
1162 ns = types.SimpleNamespace(breakfast="spam", lunch="spam")
1163
Eric Snow9d05c8c2013-02-16 18:20:32 -07001164 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1165 pname = "protocol {}".format(protocol)
1166 try:
1167 ns_pickled = pickle.dumps(ns, protocol)
1168 except TypeError as e:
1169 raise TypeError(pname) from e
1170 ns_roundtrip = pickle.loads(ns_pickled)
Eric Snowb5c8f922013-02-16 16:32:39 -07001171
Eric Snow9d05c8c2013-02-16 18:20:32 -07001172 self.assertEqual(ns, ns_roundtrip, pname)
Eric Snowb5c8f922013-02-16 16:32:39 -07001173
Barry Warsaw409da152012-06-03 16:18:47 -04001174
Thomas Wouters89f507f2006-12-13 04:49:30 +00001175if __name__ == '__main__':
Zachary Ware38c707e2015-04-13 15:00:43 -05001176 unittest.main()