| # Test the most dynamic corner cases of Python's runtime semantics. | 
 |  | 
 | import builtins | 
 | import contextlib | 
 | import unittest | 
 |  | 
 | from test.support import run_unittest, swap_item, swap_attr | 
 |  | 
 |  | 
 | class RebindBuiltinsTests(unittest.TestCase): | 
 |  | 
 |     """Test all the ways that we can change/shadow globals/builtins.""" | 
 |  | 
 |     def configure_func(self, func, *args): | 
 |         """Perform TestCase-specific configuration on a function before testing. | 
 |  | 
 |         By default, this does nothing. Example usage: spinning a function so | 
 |         that a JIT will optimize it. Subclasses should override this as needed. | 
 |  | 
 |         Args: | 
 |             func: function to configure. | 
 |             *args: any arguments that should be passed to func, if calling it. | 
 |  | 
 |         Returns: | 
 |             Nothing. Work will be performed on func in-place. | 
 |         """ | 
 |         pass | 
 |  | 
 |     def test_globals_shadow_builtins(self): | 
 |         # Modify globals() to shadow an entry in builtins. | 
 |         def foo(): | 
 |             return len([1, 2, 3]) | 
 |         self.configure_func(foo) | 
 |  | 
 |         self.assertEqual(foo(), 3) | 
 |         with swap_item(globals(), "len", lambda x: 7): | 
 |             self.assertEqual(foo(), 7) | 
 |  | 
 |     def test_modify_builtins(self): | 
 |         # Modify the builtins module directly. | 
 |         def foo(): | 
 |             return len([1, 2, 3]) | 
 |         self.configure_func(foo) | 
 |  | 
 |         self.assertEqual(foo(), 3) | 
 |         with swap_attr(builtins, "len", lambda x: 7): | 
 |             self.assertEqual(foo(), 7) | 
 |  | 
 |     def test_modify_builtins_while_generator_active(self): | 
 |         # Modify the builtins out from under a live generator. | 
 |         def foo(): | 
 |             x = range(3) | 
 |             yield len(x) | 
 |             yield len(x) | 
 |         self.configure_func(foo) | 
 |  | 
 |         g = foo() | 
 |         self.assertEqual(next(g), 3) | 
 |         with swap_attr(builtins, "len", lambda x: 7): | 
 |             self.assertEqual(next(g), 7) | 
 |  | 
 |     def test_modify_builtins_from_leaf_function(self): | 
 |         # Verify that modifications made by leaf functions percolate up the | 
 |         # callstack. | 
 |         with swap_attr(builtins, "len", len): | 
 |             def bar(): | 
 |                 builtins.len = lambda x: 4 | 
 |  | 
 |             def foo(modifier): | 
 |                 l = [] | 
 |                 l.append(len(range(7))) | 
 |                 modifier() | 
 |                 l.append(len(range(7))) | 
 |                 return l | 
 |             self.configure_func(foo, lambda: None) | 
 |  | 
 |             self.assertEqual(foo(bar), [7, 4]) | 
 |  | 
 |     def test_cannot_change_globals_or_builtins_with_eval(self): | 
 |         def foo(): | 
 |             return len([1, 2, 3]) | 
 |         self.configure_func(foo) | 
 |  | 
 |         # Note that this *doesn't* change the definition of len() seen by foo(). | 
 |         builtins_dict = {"len": lambda x: 7} | 
 |         globals_dict = {"foo": foo, "__builtins__": builtins_dict, | 
 |                         "len": lambda x: 8} | 
 |         self.assertEqual(eval("foo()", globals_dict), 3) | 
 |  | 
 |         self.assertEqual(eval("foo()", {"foo": foo}), 3) | 
 |  | 
 |     def test_cannot_change_globals_or_builtins_with_exec(self): | 
 |         def foo(): | 
 |             return len([1, 2, 3]) | 
 |         self.configure_func(foo) | 
 |  | 
 |         globals_dict = {"foo": foo} | 
 |         exec("x = foo()", globals_dict) | 
 |         self.assertEqual(globals_dict["x"], 3) | 
 |  | 
 |         # Note that this *doesn't* change the definition of len() seen by foo(). | 
 |         builtins_dict = {"len": lambda x: 7} | 
 |         globals_dict = {"foo": foo, "__builtins__": builtins_dict, | 
 |                         "len": lambda x: 8} | 
 |  | 
 |         exec("x = foo()", globals_dict) | 
 |         self.assertEqual(globals_dict["x"], 3) | 
 |  | 
 |     def test_cannot_replace_builtins_dict_while_active(self): | 
 |         def foo(): | 
 |             x = range(3) | 
 |             yield len(x) | 
 |             yield len(x) | 
 |         self.configure_func(foo) | 
 |  | 
 |         g = foo() | 
 |         self.assertEqual(next(g), 3) | 
 |         with swap_item(globals(), "__builtins__", {"len": lambda x: 7}): | 
 |             self.assertEqual(next(g), 3) | 
 |  | 
 |     def test_cannot_replace_builtins_dict_between_calls(self): | 
 |         def foo(): | 
 |             return len([1, 2, 3]) | 
 |         self.configure_func(foo) | 
 |  | 
 |         self.assertEqual(foo(), 3) | 
 |         with swap_item(globals(), "__builtins__", {"len": lambda x: 7}): | 
 |             self.assertEqual(foo(), 3) | 
 |  | 
 |     def test_eval_gives_lambda_custom_globals(self): | 
 |         globals_dict = {"len": lambda x: 7} | 
 |         foo = eval("lambda: len([])", globals_dict) | 
 |         self.configure_func(foo) | 
 |  | 
 |         self.assertEqual(foo(), 7) | 
 |  | 
 |  | 
 | def test_main(): | 
 |     run_unittest(RebindBuiltinsTests) | 
 |  | 
 |  | 
 | if __name__ == "__main__": | 
 |     test_main() |