]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] gh-94808: Cover `LOAD_GLOBAL` for custom dict subtypes (GH-96767) (GH-99091)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 4 Nov 2022 11:12:42 +0000 (04:12 -0700)
committerGitHub <noreply@github.com>
Fri, 4 Nov 2022 11:12:42 +0000 (11:12 +0000)
Lib/test/test_builtin.py

index 64c74ec2c59ae030ac6102403083959829f3a798..4cc9315eba4477d966ef8024e893fafe04a0b3a1 100644 (file)
@@ -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()