diff options
author | Collin Winter <collinw@gmail.com> | 2010-03-17 00:41:56 (GMT) |
---|---|---|
committer | Collin Winter <collinw@gmail.com> | 2010-03-17 00:41:56 (GMT) |
commit | f2bf2b3ec4a15e479933c136f2ccbde0a45a3f8e (patch) | |
tree | e1e5224e34c11ae7b3603ec4c03df601aca46048 /Lib/test/test_dynamic.py | |
parent | 0077b65a9e8ce12dd0ebb4793416cf54ddfe5374 (diff) | |
download | cpython-f2bf2b3ec4a15e479933c136f2ccbde0a45a3f8e.zip cpython-f2bf2b3ec4a15e479933c136f2ccbde0a45a3f8e.tar.gz cpython-f2bf2b3ec4a15e479933c136f2ccbde0a45a3f8e.tar.bz2 |
Add some tests for ways users can change or shadow globals and builtins.
Diffstat (limited to 'Lib/test/test_dynamic.py')
-rw-r--r-- | Lib/test/test_dynamic.py | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py new file mode 100644 index 0000000..beb7b1c --- /dev/null +++ b/Lib/test/test_dynamic.py @@ -0,0 +1,143 @@ +# 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() |