blob: 32dd656e53adea331f44ebbfffbcfb5a89124c70 [file] [log] [blame]
Raymond Hettinger8a99b502003-06-23 13:36:57 +00001import unittest
Raymond Hettinger8a99b502003-06-23 13:36:57 +00002import sys
Martin v. Löwis618dc5e2008-03-30 20:03:44 +00003import _ast
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004from test import support
Peter Schneider-Kampfdee0f02000-07-25 22:15:45 +00005
Raymond Hettinger8a99b502003-06-23 13:36:57 +00006class TestSpecifics(unittest.TestCase):
Jeremy Hylton778e2652001-11-09 19:50:08 +00007
Raymond Hettinger8a99b502003-06-23 13:36:57 +00008 def test_debug_assignment(self):
9 # catch assignments to __debug__
10 self.assertRaises(SyntaxError, compile, '__debug__ = 1', '?', 'single')
Georg Brandl1a3284e2007-12-02 09:40:06 +000011 import builtins
12 prev = builtins.__debug__
13 setattr(builtins, '__debug__', 'sure')
14 setattr(builtins, '__debug__', prev)
Jeremy Hylton778e2652001-11-09 19:50:08 +000015
Raymond Hettinger8a99b502003-06-23 13:36:57 +000016 def test_argument_handling(self):
17 # detect duplicate positional and keyword arguments
18 self.assertRaises(SyntaxError, eval, 'lambda a,a:0')
19 self.assertRaises(SyntaxError, eval, 'lambda a,a=1:0')
20 self.assertRaises(SyntaxError, eval, 'lambda a=1,a=1:0')
Benjamin Petersonec19d952008-06-30 15:01:21 +000021 self.assertRaises(SyntaxError, exec, 'def f(a, a): pass')
22 self.assertRaises(SyntaxError, exec, 'def f(a = 0, a = 1): pass')
23 self.assertRaises(SyntaxError, exec, 'def f(a): global a; a = 1')
Jeremy Hylton778e2652001-11-09 19:50:08 +000024
Raymond Hettinger8a99b502003-06-23 13:36:57 +000025 def test_syntax_error(self):
26 self.assertRaises(SyntaxError, compile, "1+*3", "filename", "exec")
Peter Schneider-Kampfdee0f02000-07-25 22:15:45 +000027
Guido van Rossumcd16bf62007-06-13 18:07:49 +000028 def test_none_keyword_arg(self):
29 self.assertRaises(SyntaxError, compile, "f(None=1)", "<string>", "exec")
30
Raymond Hettinger8a99b502003-06-23 13:36:57 +000031 def test_duplicate_global_local(self):
Benjamin Petersonec19d952008-06-30 15:01:21 +000032 self.assertRaises(SyntaxError, exec, 'def f(a): global a; a = 1')
Peter Schneider-Kampfdee0f02000-07-25 22:15:45 +000033
Raymond Hettinger66bd2332004-08-02 08:30:07 +000034 def test_exec_with_general_mapping_for_locals(self):
35
36 class M:
37 "Test mapping interface versus possible calls from eval()."
38 def __getitem__(self, key):
39 if key == 'a':
40 return 12
41 raise KeyError
42 def __setitem__(self, key, value):
43 self.results = (key, value)
Guido van Rossum63eecc72007-02-22 23:55:25 +000044 def keys(self):
45 return list('xyz')
Raymond Hettinger66bd2332004-08-02 08:30:07 +000046
47 m = M()
48 g = globals()
Georg Brandl7cae87c2006-09-06 06:51:57 +000049 exec('z = a', g, m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000050 self.assertEqual(m.results, ('z', 12))
51 try:
Georg Brandl7cae87c2006-09-06 06:51:57 +000052 exec('z = b', g, m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000053 except NameError:
54 pass
55 else:
56 self.fail('Did not detect a KeyError')
Georg Brandl7cae87c2006-09-06 06:51:57 +000057 exec('z = dir()', g, m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000058 self.assertEqual(m.results, ('z', list('xyz')))
Georg Brandl7cae87c2006-09-06 06:51:57 +000059 exec('z = globals()', g, m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000060 self.assertEqual(m.results, ('z', g))
Georg Brandl7cae87c2006-09-06 06:51:57 +000061 exec('z = locals()', g, m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000062 self.assertEqual(m.results, ('z', m))
Benjamin Petersonec19d952008-06-30 15:01:21 +000063 self.assertRaises(TypeError, exec, 'z = b', m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000064
65 class A:
66 "Non-mapping"
67 pass
68 m = A()
Benjamin Petersonec19d952008-06-30 15:01:21 +000069 self.assertRaises(TypeError, exec, 'z = a', g, m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000070
71 # Verify that dict subclasses work as well
72 class D(dict):
73 def __getitem__(self, key):
74 if key == 'a':
75 return 12
76 return dict.__getitem__(self, key)
77 d = D()
Georg Brandl7cae87c2006-09-06 06:51:57 +000078 exec('z = a', g, d)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000079 self.assertEqual(d['z'], 12)
80
Neal Norwitz6ab080c2005-10-24 00:08:10 +000081 def test_extended_arg(self):
82 longexpr = 'x = x or ' + '-x' * 2500
Georg Brandl7cae87c2006-09-06 06:51:57 +000083 g = {}
Neal Norwitz6ab080c2005-10-24 00:08:10 +000084 code = '''
85def f(x):
86 %s
87 %s
88 %s
89 %s
90 %s
91 %s
92 %s
93 %s
94 %s
95 %s
96 # the expressions above have no effect, x == argument
97 while x:
98 x -= 1
99 # EXTENDED_ARG/JUMP_ABSOLUTE here
100 return x
101''' % ((longexpr,)*10)
Georg Brandl7cae87c2006-09-06 06:51:57 +0000102 exec(code, g)
103 self.assertEqual(g['f'](5), 0)
Neal Norwitz6ab080c2005-10-24 00:08:10 +0000104
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000105 def test_argument_order(self):
Benjamin Petersonec19d952008-06-30 15:01:21 +0000106 self.assertRaises(SyntaxError, exec, 'def f(a=1, b): pass')
Jeremy Hylton121b6eb2001-02-19 23:53:42 +0000107
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000108 def test_float_literals(self):
109 # testing bad float literals
110 self.assertRaises(SyntaxError, eval, "2e")
111 self.assertRaises(SyntaxError, eval, "2.0e+")
112 self.assertRaises(SyntaxError, eval, "1e-")
113 self.assertRaises(SyntaxError, eval, "3-4e/21")
Jeremy Hylton121b6eb2001-02-19 23:53:42 +0000114
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000115 def test_indentation(self):
116 # testing compile() of indented block w/o trailing newline"
117 s = """
Guido van Rossum4b499dd32003-02-13 22:07:59 +0000118if 1:
119 if 2:
120 pass"""
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000121 compile(s, "<string>", "exec")
122
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000123 # This test is probably specific to CPython and may not generalize
124 # to other implementations. We are trying to ensure that when
125 # the first line of code starts after 256, correct line numbers
126 # in tracebacks are still produced.
127 def test_leading_newlines(self):
128 s256 = "".join(["\n"] * 256 + ["spam"])
129 co = compile(s256, 'fn', 'exec')
130 self.assertEqual(co.co_firstlineno, 257)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000131 self.assertEqual(co.co_lnotab, bytes())
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000132
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000133 def test_literals_with_leading_zeroes(self):
134 for arg in ["077787", "0xj", "0x.", "0e", "090000000000000",
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000135 "080000000000000", "000000000000009", "000000000000008",
136 "0b42", "0BADCAFE", "0o123456789", "0b1.1", "0o4.2",
137 "0b101j2", "0o153j2", "0b100e1", "0o777e1", "0777",
138 "000777", "000000000000007"]:
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000139 self.assertRaises(SyntaxError, eval, arg)
140
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000141 self.assertEqual(eval("0xff"), 255)
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000142 self.assertEqual(eval("0777."), 777)
143 self.assertEqual(eval("0777.0"), 777)
144 self.assertEqual(eval("000000000000000000000000000000000000000000000000000777e0"), 777)
145 self.assertEqual(eval("0777e1"), 7770)
146 self.assertEqual(eval("0e0"), 0)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000147 self.assertEqual(eval("0000e-012"), 0)
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000148 self.assertEqual(eval("09.5"), 9.5)
149 self.assertEqual(eval("0777j"), 777j)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000150 self.assertEqual(eval("000"), 0)
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000151 self.assertEqual(eval("00j"), 0j)
152 self.assertEqual(eval("00.0"), 0)
153 self.assertEqual(eval("0e3"), 0)
154 self.assertEqual(eval("090000000000000."), 90000000000000.)
155 self.assertEqual(eval("090000000000000.0000000000000000000000"), 90000000000000.)
156 self.assertEqual(eval("090000000000000e0"), 90000000000000.)
157 self.assertEqual(eval("090000000000000e-0"), 90000000000000.)
158 self.assertEqual(eval("090000000000000j"), 90000000000000j)
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000159 self.assertEqual(eval("000000000000008."), 8.)
160 self.assertEqual(eval("000000000000009."), 9.)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000161 self.assertEqual(eval("0b101010"), 42)
162 self.assertEqual(eval("-0b000000000010"), -2)
163 self.assertEqual(eval("0o777"), 511)
164 self.assertEqual(eval("-0o0000010"), -8)
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000165
166 def test_unary_minus(self):
167 # Verify treatment of unary minus on negative numbers SF bug #660455
Christian Heimesa37d4c62007-12-04 23:02:19 +0000168 if sys.maxsize == 2147483647:
Guido van Rossum6c9e1302003-11-29 23:52:13 +0000169 # 32-bit machine
170 all_one_bits = '0xffffffff'
Guido van Rossume2a383d2007-01-15 16:59:06 +0000171 self.assertEqual(eval(all_one_bits), 4294967295)
172 self.assertEqual(eval("-" + all_one_bits), -4294967295)
Christian Heimesa37d4c62007-12-04 23:02:19 +0000173 elif sys.maxsize == 9223372036854775807:
Guido van Rossum6c9e1302003-11-29 23:52:13 +0000174 # 64-bit machine
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000175 all_one_bits = '0xffffffffffffffff'
Guido van Rossume2a383d2007-01-15 16:59:06 +0000176 self.assertEqual(eval(all_one_bits), 18446744073709551615)
177 self.assertEqual(eval("-" + all_one_bits), -18446744073709551615)
Guido van Rossum6c9e1302003-11-29 23:52:13 +0000178 else:
179 self.fail("How many bits *does* this machine have???")
Christian Heimesa37d4c62007-12-04 23:02:19 +0000180 # Verify treatment of contant folding on -(sys.maxsize+1)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000181 # i.e. -2147483648 on 32 bit platforms. Should return int, not long.
Christian Heimesa37d4c62007-12-04 23:02:19 +0000182 self.assertTrue(isinstance(eval("%s" % (-sys.maxsize - 1)), int))
183 self.assertTrue(isinstance(eval("%s" % (-sys.maxsize - 2)), int))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000184
Christian Heimesa37d4c62007-12-04 23:02:19 +0000185 if sys.maxsize == 9223372036854775807:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000186 def test_32_63_bit_values(self):
187 a = +4294967296 # 1 << 32
188 b = -4294967296 # 1 << 32
189 c = +281474976710656 # 1 << 48
190 d = -281474976710656 # 1 << 48
191 e = +4611686018427387904 # 1 << 62
192 f = -4611686018427387904 # 1 << 62
193 g = +9223372036854775807 # 1 << 63 - 1
194 h = -9223372036854775807 # 1 << 63 - 1
195
Neal Norwitz221085d2007-02-25 20:55:47 +0000196 for variable in self.test_32_63_bit_values.__code__.co_consts:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000197 if variable is not None:
198 self.assertTrue(isinstance(variable, int))
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000199
200 def test_sequence_unpacking_error(self):
201 # Verify sequence packing/unpacking with "or". SF bug #757818
202 i,j = (1, -1) or (-1, 1)
203 self.assertEqual(i, 1)
204 self.assertEqual(j, -1)
Guido van Rossum4b499dd32003-02-13 22:07:59 +0000205
Raymond Hettinger11a70c72004-07-17 21:46:25 +0000206 def test_none_assignment(self):
207 stmts = [
208 'None = 0',
209 'None += 0',
210 '__builtins__.None = 0',
211 'def None(): pass',
212 'class None: pass',
213 '(a, None) = 0, 0',
214 'for None in range(10): pass',
215 'def f(None): pass',
Benjamin Peterson78565b22009-06-28 19:19:51 +0000216 'import None',
217 'import x as None',
218 'from x import None',
219 'from x import y as None'
Raymond Hettinger11a70c72004-07-17 21:46:25 +0000220 ]
221 for stmt in stmts:
222 stmt += "\n"
223 self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single')
224 self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
Tim Petersd507dab2001-08-30 20:51:59 +0000225
Anthony Baxter1a4ddae2004-08-31 10:07:13 +0000226 def test_import(self):
227 succeed = [
228 'import sys',
229 'import os, sys',
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000230 'import os as bar',
231 'import os.path as bar',
Anthony Baxter1a4ddae2004-08-31 10:07:13 +0000232 'from __future__ import nested_scopes, generators',
233 'from __future__ import (nested_scopes,\ngenerators)',
234 'from __future__ import (nested_scopes,\ngenerators,)',
235 'from sys import stdin, stderr, stdout',
236 'from sys import (stdin, stderr,\nstdout)',
237 'from sys import (stdin, stderr,\nstdout,)',
238 'from sys import (stdin\n, stderr, stdout)',
239 'from sys import (stdin\n, stderr, stdout,)',
240 'from sys import stdin as si, stdout as so, stderr as se',
241 'from sys import (stdin as si, stdout as so, stderr as se)',
242 'from sys import (stdin as si, stdout as so, stderr as se,)',
243 ]
244 fail = [
245 'import (os, sys)',
246 'import (os), (sys)',
247 'import ((os), (sys))',
248 'import (sys',
249 'import sys)',
250 'import (os,)',
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000251 'import os As bar',
252 'import os.path a bar',
253 'from sys import stdin As stdout',
254 'from sys import stdin a stdout',
Anthony Baxter1a4ddae2004-08-31 10:07:13 +0000255 'from (sys) import stdin',
256 'from __future__ import (nested_scopes',
257 'from __future__ import nested_scopes)',
258 'from __future__ import nested_scopes,\ngenerators',
259 'from sys import (stdin',
260 'from sys import stdin)',
261 'from sys import stdin, stdout,\nstderr',
262 'from sys import stdin si',
263 'from sys import stdin,'
264 'from sys import (*)',
265 'from sys import (stdin,, stdout, stderr)',
266 'from sys import (stdin, stdout),',
267 ]
268 for stmt in succeed:
269 compile(stmt, 'tmp', 'exec')
270 for stmt in fail:
271 self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
272
Raymond Hettinger9047c8f2004-10-24 00:10:06 +0000273 def test_for_distinct_code_objects(self):
274 # SF bug 1048870
275 def f():
276 f1 = lambda x=1: x
277 f2 = lambda x=2: x
278 return f1, f2
279 f1, f2 = f()
Neal Norwitz221085d2007-02-25 20:55:47 +0000280 self.assertNotEqual(id(f1.__code__), id(f2.__code__))
Raymond Hettinger9047c8f2004-10-24 00:10:06 +0000281
Guido van Rossumf8761c72007-07-22 20:01:13 +0000282## def test_unicode_encoding(self):
283## code = "# -*- coding: utf-8 -*-\npass\n"
284## self.assertRaises(SyntaxError, compile, code, "tmp", "exec")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000285
Nick Coghlaneadee9a2006-03-13 12:31:58 +0000286 def test_subscripts(self):
287 # SF bug 1448804
288 # Class to make testing subscript results easy
289 class str_map(object):
290 def __init__(self):
291 self.data = {}
292 def __getitem__(self, key):
293 return self.data[str(key)]
294 def __setitem__(self, key, value):
295 self.data[str(key)] = value
296 def __delitem__(self, key):
297 del self.data[str(key)]
298 def __contains__(self, key):
299 return str(key) in self.data
300 d = str_map()
301 # Index
302 d[1] = 1
303 self.assertEqual(d[1], 1)
304 d[1] += 1
305 self.assertEqual(d[1], 2)
306 del d[1]
307 self.assertEqual(1 in d, False)
308 # Tuple of indices
309 d[1, 1] = 1
310 self.assertEqual(d[1, 1], 1)
311 d[1, 1] += 1
312 self.assertEqual(d[1, 1], 2)
313 del d[1, 1]
314 self.assertEqual((1, 1) in d, False)
315 # Simple slice
316 d[1:2] = 1
317 self.assertEqual(d[1:2], 1)
318 d[1:2] += 1
319 self.assertEqual(d[1:2], 2)
320 del d[1:2]
321 self.assertEqual(slice(1, 2) in d, False)
322 # Tuple of simple slices
323 d[1:2, 1:2] = 1
324 self.assertEqual(d[1:2, 1:2], 1)
325 d[1:2, 1:2] += 1
326 self.assertEqual(d[1:2, 1:2], 2)
327 del d[1:2, 1:2]
328 self.assertEqual((slice(1, 2), slice(1, 2)) in d, False)
329 # Extended slice
330 d[1:2:3] = 1
331 self.assertEqual(d[1:2:3], 1)
332 d[1:2:3] += 1
333 self.assertEqual(d[1:2:3], 2)
334 del d[1:2:3]
335 self.assertEqual(slice(1, 2, 3) in d, False)
336 # Tuple of extended slices
337 d[1:2:3, 1:2:3] = 1
338 self.assertEqual(d[1:2:3, 1:2:3], 1)
339 d[1:2:3, 1:2:3] += 1
340 self.assertEqual(d[1:2:3, 1:2:3], 2)
341 del d[1:2:3, 1:2:3]
342 self.assertEqual((slice(1, 2, 3), slice(1, 2, 3)) in d, False)
343 # Ellipsis
344 d[...] = 1
345 self.assertEqual(d[...], 1)
346 d[...] += 1
347 self.assertEqual(d[...], 2)
348 del d[...]
349 self.assertEqual(Ellipsis in d, False)
350 # Tuple of Ellipses
351 d[..., ...] = 1
352 self.assertEqual(d[..., ...], 1)
353 d[..., ...] += 1
354 self.assertEqual(d[..., ...], 2)
355 del d[..., ...]
356 self.assertEqual((Ellipsis, Ellipsis) in d, False)
357
Guido van Rossum0240b922007-02-26 21:23:50 +0000358 def test_annotation_limit(self):
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000359 # 16 bits are available for # of annotations, but only 8 bits are
360 # available for the parameter count, hence 255
Guido van Rossum0240b922007-02-26 21:23:50 +0000361 # is the max. Ensure the result of too many annotations is a
362 # SyntaxError.
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000363 s = "def f(%s): pass"
364 s %= ', '.join('a%d:%d' % (i,i) for i in range(256))
Guido van Rossum0240b922007-02-26 21:23:50 +0000365 self.assertRaises(SyntaxError, compile, s, '?', 'exec')
366 # Test that the max # of annotations compiles.
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000367 s = "def f(%s): pass"
368 s %= ', '.join('a%d:%d' % (i,i) for i in range(255))
Guido van Rossum0240b922007-02-26 21:23:50 +0000369 compile(s, '?', 'exec')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000370
371 def test_mangling(self):
372 class A:
373 def f():
374 __mangled = 1
375 __not_mangled__ = 2
376 import __mangled_mod
377 import __package__.module
378
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000379 self.assertTrue("_A__mangled" in A.f.__code__.co_varnames)
380 self.assertTrue("__not_mangled__" in A.f.__code__.co_varnames)
381 self.assertTrue("_A__mangled_mod" in A.f.__code__.co_varnames)
382 self.assertTrue("__package__" in A.f.__code__.co_varnames)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000383
Martin v. Löwis618dc5e2008-03-30 20:03:44 +0000384 def test_compile_ast(self):
385 fname = __file__
386 if fname.lower().endswith(('pyc', 'pyo')):
387 fname = fname[:-1]
388 with open(fname, 'r') as f:
389 fcontents = f.read()
390 sample_code = [
391 ['<assign>', 'x = 5'],
392 ['<ifblock>', """if True:\n pass\n"""],
393 ['<forblock>', """for n in [1, 2, 3]:\n print(n)\n"""],
394 ['<deffunc>', """def foo():\n pass\nfoo()\n"""],
395 [fname, fcontents],
396 ]
397
398 for fname, code in sample_code:
399 co1 = compile(code, '%s1' % fname, 'exec')
400 ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000401 self.assertTrue(type(ast) == _ast.Module)
Martin v. Löwis618dc5e2008-03-30 20:03:44 +0000402 co2 = compile(ast, '%s3' % fname, 'exec')
403 self.assertEqual(co1, co2)
Neal Norwitzdb4115f2008-03-31 04:20:05 +0000404 # the code object's filename comes from the second compilation step
405 self.assertEqual(co2.co_filename, '%s3' % fname)
406
407 # raise exception when node type doesn't match with compile mode
408 co1 = compile('print(1)', '<string>', 'exec', _ast.PyCF_ONLY_AST)
409 self.assertRaises(TypeError, compile, co1, '<ast>', 'eval')
410
411 # raise exception when node type is no start node
412 self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec')
413
414 # raise exception when node has invalid children
415 ast = _ast.Module()
416 ast.body = [_ast.BoolOp()]
417 self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
Martin v. Löwis618dc5e2008-03-30 20:03:44 +0000418
419
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000420def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000421 support.run_unittest(TestSpecifics)
Tim Petersd507dab2001-08-30 20:51:59 +0000422
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000423if __name__ == "__main__":
424 test_main()