summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_capi/test_eval_code_ex.py
blob: b298e5007e5e7db6529767ff5895fa3230c7a664 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import unittest
import builtins
from collections import UserDict

from test.support import import_helper
from test.support import swap_attr


# Skip this test if the _testcapi module isn't available.
_testcapi = import_helper.import_module('_testcapi')

NULL = None


class PyEval_EvalCodeExTests(unittest.TestCase):

    def test_simple(self):
        def f():
            return a

        eval_code_ex = _testcapi.eval_code_ex
        code = f.__code__
        self.assertEqual(eval_code_ex(code, dict(a=1)), 1)

        self.assertRaises(NameError, eval_code_ex, code, {})
        self.assertRaises(SystemError, eval_code_ex, code, UserDict(a=1))
        self.assertRaises(SystemError, eval_code_ex, code, [])
        self.assertRaises(SystemError, eval_code_ex, code, 1)
        # CRASHES eval_code_ex(code, NULL)
        # CRASHES eval_code_ex(1, {})
        # CRASHES eval_code_ex(NULL, {})

    def test_custom_locals(self):
        # Monkey-patch __build_class__ to get a class code object.
        code = None
        def build_class(func, name, /, *bases, **kwds):
            nonlocal code
            code = func.__code__

        with swap_attr(builtins, '__build_class__', build_class):
            class A:
                # Uses LOAD_NAME for a
                r[:] = [a]

        eval_code_ex = _testcapi.eval_code_ex
        results = []
        g = dict(a=1, r=results)
        self.assertIsNone(eval_code_ex(code, g))
        self.assertEqual(results, [1])
        self.assertIsNone(eval_code_ex(code, g, dict(a=2)))
        self.assertEqual(results, [2])
        self.assertIsNone(eval_code_ex(code, g, UserDict(a=3)))
        self.assertEqual(results, [3])
        self.assertIsNone(eval_code_ex(code, g, {}))
        self.assertEqual(results, [1])
        self.assertIsNone(eval_code_ex(code, g, NULL))
        self.assertEqual(results, [1])

        self.assertRaises(TypeError, eval_code_ex, code, g, [])
        self.assertRaises(TypeError, eval_code_ex, code, g, 1)
        self.assertRaises(NameError, eval_code_ex, code, dict(r=results), {})
        self.assertRaises(NameError, eval_code_ex, code, dict(r=results), NULL)
        self.assertRaises(TypeError, eval_code_ex, code, dict(r=results), [])
        self.assertRaises(TypeError, eval_code_ex, code, dict(r=results), 1)

    def test_with_args(self):
        def f(a, b, c):
            return a

        eval_code_ex = _testcapi.eval_code_ex
        code = f.__code__
        self.assertEqual(eval_code_ex(code, {}, {}, (1, 2, 3)), 1)
        self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (1, 2))
        self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (1, 2, 3, 4))

    def test_with_kwargs(self):
        def f(a, b, c):
            return a

        eval_code_ex = _testcapi.eval_code_ex
        code = f.__code__
        self.assertEqual(eval_code_ex(code, {}, {}, (), dict(a=1, b=2, c=3)), 1)
        self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (), dict(a=1, b=2))
        self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (), dict(a=1, b=2))
        self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (), dict(a=1, b=2, c=3, d=4))

    def test_with_default(self):
        def f(a):
            return a

        eval_code_ex = _testcapi.eval_code_ex
        code = f.__code__
        self.assertEqual(eval_code_ex(code, {}, {}, (), {}, (1,)), 1)
        self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (), {}, ())

    def test_with_kwarg_default(self):
        def f(*, a):
            return a

        eval_code_ex = _testcapi.eval_code_ex
        code = f.__code__
        self.assertEqual(eval_code_ex(code, {}, {}, (), {}, (), dict(a=1)), 1)
        self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (), {}, (), {})
        self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (), {}, (), NULL)
        self.assertRaises(SystemError, eval_code_ex, code, {}, {}, (), {}, (), UserDict(a=1))
        self.assertRaises(SystemError, eval_code_ex, code, {}, {}, (), {}, (), [])
        self.assertRaises(SystemError, eval_code_ex, code, {}, {}, (), {}, (), 1)

    def test_with_closure(self):
        a = 1
        b = 2
        def f():
            b
            return a

        eval_code_ex = _testcapi.eval_code_ex
        code = f.__code__
        self.assertEqual(eval_code_ex(code, {}, {}, (), {}, (), {}, f.__closure__), 1)
        self.assertEqual(eval_code_ex(code, {}, {}, (), {}, (), {}, f.__closure__[::-1]), 2)

        # CRASHES eval_code_ex(code, {}, {}, (), {}, (), {}, ()), 1)
        # CRASHES eval_code_ex(code, {}, {}, (), {}, (), {}, NULL), 1)


if __name__ == "__main__":
    unittest.main()