blob: 3ae090fd66ae25e41c99f1bd435f0afed67d6fa4 [file] [log] [blame]
Collin Winterf2bf2b32010-03-17 00:41:56 +00001# Test the most dynamic corner cases of Python's runtime semantics.
2
3import builtins
Collin Winterf2bf2b32010-03-17 00:41:56 +00004import unittest
5
Zachary Ware38c707e2015-04-13 15:00:43 -05006from test.support import swap_item, swap_attr
Collin Winterf2bf2b32010-03-17 00:41:56 +00007
8
9class RebindBuiltinsTests(unittest.TestCase):
10
11 """Test all the ways that we can change/shadow globals/builtins."""
12
13 def configure_func(self, func, *args):
14 """Perform TestCase-specific configuration on a function before testing.
15
16 By default, this does nothing. Example usage: spinning a function so
17 that a JIT will optimize it. Subclasses should override this as needed.
18
19 Args:
20 func: function to configure.
21 *args: any arguments that should be passed to func, if calling it.
22
23 Returns:
24 Nothing. Work will be performed on func in-place.
25 """
26 pass
27
28 def test_globals_shadow_builtins(self):
29 # Modify globals() to shadow an entry in builtins.
30 def foo():
31 return len([1, 2, 3])
32 self.configure_func(foo)
33
34 self.assertEqual(foo(), 3)
35 with swap_item(globals(), "len", lambda x: 7):
36 self.assertEqual(foo(), 7)
37
38 def test_modify_builtins(self):
39 # Modify the builtins module directly.
40 def foo():
41 return len([1, 2, 3])
42 self.configure_func(foo)
43
44 self.assertEqual(foo(), 3)
45 with swap_attr(builtins, "len", lambda x: 7):
46 self.assertEqual(foo(), 7)
47
48 def test_modify_builtins_while_generator_active(self):
49 # Modify the builtins out from under a live generator.
50 def foo():
51 x = range(3)
52 yield len(x)
53 yield len(x)
54 self.configure_func(foo)
55
56 g = foo()
57 self.assertEqual(next(g), 3)
58 with swap_attr(builtins, "len", lambda x: 7):
59 self.assertEqual(next(g), 7)
60
61 def test_modify_builtins_from_leaf_function(self):
62 # Verify that modifications made by leaf functions percolate up the
63 # callstack.
64 with swap_attr(builtins, "len", len):
65 def bar():
66 builtins.len = lambda x: 4
67
68 def foo(modifier):
69 l = []
70 l.append(len(range(7)))
71 modifier()
72 l.append(len(range(7)))
73 return l
74 self.configure_func(foo, lambda: None)
75
76 self.assertEqual(foo(bar), [7, 4])
77
78 def test_cannot_change_globals_or_builtins_with_eval(self):
79 def foo():
80 return len([1, 2, 3])
81 self.configure_func(foo)
82
83 # Note that this *doesn't* change the definition of len() seen by foo().
84 builtins_dict = {"len": lambda x: 7}
85 globals_dict = {"foo": foo, "__builtins__": builtins_dict,
86 "len": lambda x: 8}
87 self.assertEqual(eval("foo()", globals_dict), 3)
88
89 self.assertEqual(eval("foo()", {"foo": foo}), 3)
90
91 def test_cannot_change_globals_or_builtins_with_exec(self):
92 def foo():
93 return len([1, 2, 3])
94 self.configure_func(foo)
95
96 globals_dict = {"foo": foo}
97 exec("x = foo()", globals_dict)
98 self.assertEqual(globals_dict["x"], 3)
99
100 # Note that this *doesn't* change the definition of len() seen by foo().
101 builtins_dict = {"len": lambda x: 7}
102 globals_dict = {"foo": foo, "__builtins__": builtins_dict,
103 "len": lambda x: 8}
104
105 exec("x = foo()", globals_dict)
106 self.assertEqual(globals_dict["x"], 3)
107
108 def test_cannot_replace_builtins_dict_while_active(self):
109 def foo():
110 x = range(3)
111 yield len(x)
112 yield len(x)
113 self.configure_func(foo)
114
115 g = foo()
116 self.assertEqual(next(g), 3)
117 with swap_item(globals(), "__builtins__", {"len": lambda x: 7}):
118 self.assertEqual(next(g), 3)
119
120 def test_cannot_replace_builtins_dict_between_calls(self):
121 def foo():
122 return len([1, 2, 3])
123 self.configure_func(foo)
124
125 self.assertEqual(foo(), 3)
126 with swap_item(globals(), "__builtins__", {"len": lambda x: 7}):
127 self.assertEqual(foo(), 3)
128
129 def test_eval_gives_lambda_custom_globals(self):
130 globals_dict = {"len": lambda x: 7}
131 foo = eval("lambda: len([])", globals_dict)
132 self.configure_func(foo)
133
134 self.assertEqual(foo(), 7)
135
136
Collin Winterf2bf2b32010-03-17 00:41:56 +0000137if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -0500138 unittest.main()