test_compile.py revision 28746aba9bf636d03eb1c1c5f4550c6f2dbf5300
1import unittest
2import warnings
3import sys
4from test import test_support
5
6class TestSpecifics(unittest.TestCase):
7
8    def test_debug_assignment(self):
9        # catch assignments to __debug__
10        self.assertRaises(SyntaxError, compile, '__debug__ = 1', '?', 'single')
11        import __builtin__
12        prev = __builtin__.__debug__
13        setattr(__builtin__, '__debug__', 'sure')
14        setattr(__builtin__, '__debug__', prev)
15
16    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')
21        try:
22            exec 'def f(a, a): pass'
23            self.fail("duplicate arguments")
24        except SyntaxError:
25            pass
26        try:
27            exec 'def f(a = 0, a = 1): pass'
28            self.fail("duplicate keyword arguments")
29        except SyntaxError:
30            pass
31        try:
32            exec 'def f(a): global a; a = 1'
33            self.fail("variable is global and local")
34        except SyntaxError:
35            pass
36
37    def test_syntax_error(self):
38        self.assertRaises(SyntaxError, compile, "1+*3", "filename", "exec")
39
40    def test_duplicate_global_local(self):
41        try:
42            exec 'def f(a): global a; a = 1'
43            self.fail("variable is global and local")
44        except SyntaxError:
45            pass
46
47    def test_exec_with_general_mapping_for_locals(self):
48
49        class M:
50            "Test mapping interface versus possible calls from eval()."
51            def __getitem__(self, key):
52                if key == 'a':
53                    return 12
54                raise KeyError
55            def __setitem__(self, key, value):
56                self.results = (key, value)
57            def keys(self):
58                return list('xyz')
59
60        m = M()
61        g = globals()
62        exec 'z = a' in g, m
63        self.assertEqual(m.results, ('z', 12))
64        try:
65            exec 'z = b' in g, m
66        except NameError:
67            pass
68        else:
69            self.fail('Did not detect a KeyError')
70        exec 'z = dir()' in g, m
71        self.assertEqual(m.results, ('z', list('xyz')))
72        exec 'z = globals()' in g, m
73        self.assertEqual(m.results, ('z', g))
74        exec 'z = locals()' in g, m
75        self.assertEqual(m.results, ('z', m))
76        try:
77            exec 'z = b' in m
78        except TypeError:
79            pass
80        else:
81            self.fail('Did not validate globals as a real dict')
82
83        class A:
84            "Non-mapping"
85            pass
86        m = A()
87        try:
88            exec 'z = a' in g, m
89        except TypeError:
90            pass
91        else:
92            self.fail('Did not validate locals as a mapping')
93
94        # Verify that dict subclasses work as well
95        class D(dict):
96            def __getitem__(self, key):
97                if key == 'a':
98                    return 12
99                return dict.__getitem__(self, key)
100        d = D()
101        exec 'z = a' in g, d
102        self.assertEqual(d['z'], 12)
103
104    def test_extended_arg(self):
105        longexpr = 'x = x or ' + '-x' * 2500
106        code = '''
107def f(x):
108    %s
109    %s
110    %s
111    %s
112    %s
113    %s
114    %s
115    %s
116    %s
117    %s
118    # the expressions above have no effect, x == argument
119    while x:
120        x -= 1
121        # EXTENDED_ARG/JUMP_ABSOLUTE here
122    return x
123''' % ((longexpr,)*10)
124        exec code
125        self.assertEqual(f(5), 0)
126
127    def test_complex_args(self):
128
129        def comp_args((a, b)):
130            return a,b
131        self.assertEqual(comp_args((1, 2)), (1, 2))
132
133        def comp_args((a, b)=(3, 4)):
134            return a, b
135        self.assertEqual(comp_args((1, 2)), (1, 2))
136        self.assertEqual(comp_args(), (3, 4))
137
138        def comp_args(a, (b, c)):
139            return a, b, c
140        self.assertEqual(comp_args(1, (2, 3)), (1, 2, 3))
141
142        def comp_args(a=2, (b, c)=(3, 4)):
143            return a, b, c
144        self.assertEqual(comp_args(1, (2, 3)), (1, 2, 3))
145        self.assertEqual(comp_args(), (2, 3, 4))
146
147    def test_argument_order(self):
148        try:
149            exec 'def f(a=1, (b, c)): pass'
150            self.fail("non-default args after default")
151        except SyntaxError:
152            pass
153
154    def test_float_literals(self):
155        # testing bad float literals
156        self.assertRaises(SyntaxError, eval, "2e")
157        self.assertRaises(SyntaxError, eval, "2.0e+")
158        self.assertRaises(SyntaxError, eval, "1e-")
159        self.assertRaises(SyntaxError, eval, "3-4e/21")
160
161    def test_indentation(self):
162        # testing compile() of indented block w/o trailing newline"
163        s = """
164if 1:
165    if 2:
166        pass"""
167        compile(s, "<string>", "exec")
168
169    def test_literals_with_leading_zeroes(self):
170        for arg in ["077787", "0xj", "0x.", "0e",  "090000000000000",
171                    "080000000000000", "000000000000009", "000000000000008"]:
172            self.assertRaises(SyntaxError, eval, arg)
173
174        self.assertEqual(eval("0777"), 511)
175        self.assertEqual(eval("0777L"), 511)
176        self.assertEqual(eval("000777"), 511)
177        self.assertEqual(eval("0xff"), 255)
178        self.assertEqual(eval("0xffL"), 255)
179        self.assertEqual(eval("0XfF"), 255)
180        self.assertEqual(eval("0777."), 777)
181        self.assertEqual(eval("0777.0"), 777)
182        self.assertEqual(eval("000000000000000000000000000000000000000000000000000777e0"), 777)
183        self.assertEqual(eval("0777e1"), 7770)
184        self.assertEqual(eval("0e0"), 0)
185        self.assertEqual(eval("0000E-012"), 0)
186        self.assertEqual(eval("09.5"), 9.5)
187        self.assertEqual(eval("0777j"), 777j)
188        self.assertEqual(eval("00j"), 0j)
189        self.assertEqual(eval("00.0"), 0)
190        self.assertEqual(eval("0e3"), 0)
191        self.assertEqual(eval("090000000000000."), 90000000000000.)
192        self.assertEqual(eval("090000000000000.0000000000000000000000"), 90000000000000.)
193        self.assertEqual(eval("090000000000000e0"), 90000000000000.)
194        self.assertEqual(eval("090000000000000e-0"), 90000000000000.)
195        self.assertEqual(eval("090000000000000j"), 90000000000000j)
196        self.assertEqual(eval("000000000000007"), 7)
197        self.assertEqual(eval("000000000000008."), 8.)
198        self.assertEqual(eval("000000000000009."), 9.)
199
200    def test_unary_minus(self):
201        # Verify treatment of unary minus on negative numbers SF bug #660455
202        if sys.maxint == 2147483647:
203            # 32-bit machine
204            all_one_bits = '0xffffffff'
205            self.assertEqual(eval(all_one_bits), 4294967295L)
206            self.assertEqual(eval("-" + all_one_bits), -4294967295L)
207        elif sys.maxint == 9223372036854775807:
208            # 64-bit machine
209            all_one_bits = '0xffffffffffffffff'
210            self.assertEqual(eval(all_one_bits), 18446744073709551615L)
211            self.assertEqual(eval("-" + all_one_bits), -18446744073709551615L)
212        else:
213            self.fail("How many bits *does* this machine have???")
214        # Verify treatment of contant folding on -(sys.maxint+1)
215        # i.e. -2147483648 on 32 bit platforms.  Should return int, not long.
216        self.assertTrue(isinstance(eval("%s" % (-sys.maxint - 1)), int))
217        self.assertTrue(isinstance(eval("%s" % (-sys.maxint - 2)), long))
218
219    if sys.maxint == 9223372036854775807:
220        def test_32_63_bit_values(self):
221            a = +4294967296  # 1 << 32
222            b = -4294967296  # 1 << 32
223            c = +281474976710656  # 1 << 48
224            d = -281474976710656  # 1 << 48
225            e = +4611686018427387904  # 1 << 62
226            f = -4611686018427387904  # 1 << 62
227            g = +9223372036854775807  # 1 << 63 - 1
228            h = -9223372036854775807  # 1 << 63 - 1
229
230            for variable in self.test_32_63_bit_values.func_code.co_consts:
231                if variable is not None:
232                    self.assertTrue(isinstance(variable, int))
233
234    def test_sequence_unpacking_error(self):
235        # Verify sequence packing/unpacking with "or".  SF bug #757818
236        i,j = (1, -1) or (-1, 1)
237        self.assertEqual(i, 1)
238        self.assertEqual(j, -1)
239
240    def test_none_assignment(self):
241        stmts = [
242            'None = 0',
243            'None += 0',
244            '__builtins__.None = 0',
245            'def None(): pass',
246            'class None: pass',
247            '(a, None) = 0, 0',
248            'for None in range(10): pass',
249            'def f(None): pass',
250        ]
251        for stmt in stmts:
252            stmt += "\n"
253            self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single')
254            self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
255
256    def test_import(self):
257        succeed = [
258            'import sys',
259            'import os, sys',
260            'import os as bar',
261            'import os.path as bar',
262            'from __future__ import nested_scopes, generators',
263            'from __future__ import (nested_scopes,\ngenerators)',
264            'from __future__ import (nested_scopes,\ngenerators,)',
265            'from sys import stdin, stderr, stdout',
266            'from sys import (stdin, stderr,\nstdout)',
267            'from sys import (stdin, stderr,\nstdout,)',
268            'from sys import (stdin\n, stderr, stdout)',
269            'from sys import (stdin\n, stderr, stdout,)',
270            'from sys import stdin as si, stdout as so, stderr as se',
271            'from sys import (stdin as si, stdout as so, stderr as se)',
272            'from sys import (stdin as si, stdout as so, stderr as se,)',
273            ]
274        fail = [
275            'import (os, sys)',
276            'import (os), (sys)',
277            'import ((os), (sys))',
278            'import (sys',
279            'import sys)',
280            'import (os,)',
281            'import os As bar',
282            'import os.path a bar',
283            'from sys import stdin As stdout',
284            'from sys import stdin a stdout',
285            'from (sys) import stdin',
286            'from __future__ import (nested_scopes',
287            'from __future__ import nested_scopes)',
288            'from __future__ import nested_scopes,\ngenerators',
289            'from sys import (stdin',
290            'from sys import stdin)',
291            'from sys import stdin, stdout,\nstderr',
292            'from sys import stdin si',
293            'from sys import stdin,'
294            'from sys import (*)',
295            'from sys import (stdin,, stdout, stderr)',
296            'from sys import (stdin, stdout),',
297            ]
298        for stmt in succeed:
299            compile(stmt, 'tmp', 'exec')
300        for stmt in fail:
301            self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
302
303    def test_for_distinct_code_objects(self):
304        # SF bug 1048870
305        def f():
306            f1 = lambda x=1: x
307            f2 = lambda x=2: x
308            return f1, f2
309        f1, f2 = f()
310        self.assertNotEqual(id(f1.func_code), id(f2.func_code))
311
312    def test_unicode_encoding(self):
313        code = u"# -*- coding: utf-8 -*-\npass\n"
314        self.assertRaises(SyntaxError, compile, code, "tmp", "exec")
315
316    def test_subscripts(self):
317        # SF bug 1448804
318        # Class to make testing subscript results easy
319        class str_map(object):
320            def __init__(self):
321                self.data = {}
322            def __getitem__(self, key):
323                return self.data[str(key)]
324            def __setitem__(self, key, value):
325                self.data[str(key)] = value
326            def __delitem__(self, key):
327                del self.data[str(key)]
328            def __contains__(self, key):
329                return str(key) in self.data
330        d = str_map()
331        # Index
332        d[1] = 1
333        self.assertEqual(d[1], 1)
334        d[1] += 1
335        self.assertEqual(d[1], 2)
336        del d[1]
337        self.assertEqual(1 in d, False)
338        # Tuple of indices
339        d[1, 1] = 1
340        self.assertEqual(d[1, 1], 1)
341        d[1, 1] += 1
342        self.assertEqual(d[1, 1], 2)
343        del d[1, 1]
344        self.assertEqual((1, 1) in d, False)
345        # Simple slice
346        d[1:2] = 1
347        self.assertEqual(d[1:2], 1)
348        d[1:2] += 1
349        self.assertEqual(d[1:2], 2)
350        del d[1:2]
351        self.assertEqual(slice(1, 2) in d, False)
352        # Tuple of simple slices
353        d[1:2, 1:2] = 1
354        self.assertEqual(d[1:2, 1:2], 1)
355        d[1:2, 1:2] += 1
356        self.assertEqual(d[1:2, 1:2], 2)
357        del d[1:2, 1:2]
358        self.assertEqual((slice(1, 2), slice(1, 2)) in d, False)
359        # Extended slice
360        d[1:2:3] = 1
361        self.assertEqual(d[1:2:3], 1)
362        d[1:2:3] += 1
363        self.assertEqual(d[1:2:3], 2)
364        del d[1:2:3]
365        self.assertEqual(slice(1, 2, 3) in d, False)
366        # Tuple of extended slices
367        d[1:2:3, 1:2:3] = 1
368        self.assertEqual(d[1:2:3, 1:2:3], 1)
369        d[1:2:3, 1:2:3] += 1
370        self.assertEqual(d[1:2:3, 1:2:3], 2)
371        del d[1:2:3, 1:2:3]
372        self.assertEqual((slice(1, 2, 3), slice(1, 2, 3)) in d, False)
373        # Ellipsis
374        d[...] = 1
375        self.assertEqual(d[...], 1)
376        d[...] += 1
377        self.assertEqual(d[...], 2)
378        del d[...]
379        self.assertEqual(Ellipsis in d, False)
380        # Tuple of Ellipses
381        d[..., ...] = 1
382        self.assertEqual(d[..., ...], 1)
383        d[..., ...] += 1
384        self.assertEqual(d[..., ...], 2)
385        del d[..., ...]
386        self.assertEqual((Ellipsis, Ellipsis) in d, False)
387
388def test_main():
389    test_support.run_unittest(TestSpecifics)
390
391if __name__ == "__main__":
392    test_main()
393