From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Fri, 4 Nov 2022 11:12:42 +0000 (-0700) Subject: [3.11] gh-94808: Cover `LOAD_GLOBAL` for custom dict subtypes (GH-96767) (GH-99091) X-Git-Tag: v3.11.1~146 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2b79f4e469450d28ae0db593782500312f747451;p=thirdparty%2FPython%2Fcpython.git [3.11] gh-94808: Cover `LOAD_GLOBAL` for custom dict subtypes (GH-96767) (GH-99091) --- diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 64c74ec2c59a..4cc9315eba44 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -737,6 +737,7 @@ class BuiltinTest(unittest.TestCase): self.assertRaises(TypeError, exec, code, {'__builtins__': 123}) + def test_exec_globals_frozen(self): class frozendict_error(Exception): pass @@ -768,6 +769,36 @@ class BuiltinTest(unittest.TestCase): self.assertRaises(frozendict_error, exec, code, namespace) + def test_exec_globals_error_on_get(self): + # custom `globals` or `builtins` can raise errors on item access + class setonlyerror(Exception): + pass + + class setonlydict(dict): + def __getitem__(self, key): + raise setonlyerror + + # globals' `__getitem__` raises + code = compile("globalname", "test", "exec") + self.assertRaises(setonlyerror, + exec, code, setonlydict({'globalname': 1})) + + # builtins' `__getitem__` raises + code = compile("superglobal", "test", "exec") + self.assertRaises(setonlyerror, exec, code, + {'__builtins__': setonlydict({'superglobal': 1})}) + + def test_exec_globals_dict_subclass(self): + class customdict(dict): # this one should not do anything fancy + pass + + code = compile("superglobal", "test", "exec") + # works correctly + exec(code, {'__builtins__': customdict({'superglobal': 1})}) + # custom builtins dict subclass is missing key + self.assertRaisesRegex(NameError, "name 'superglobal' is not defined", + exec, code, {'__builtins__': customdict()}) + def test_exec_redirected(self): savestdout = sys.stdout sys.stdout = None # Whatever that cannot flush()