Author: Carl Friedrich Bolz-Tereick <[email protected]>
Branch: py3.6
Changeset: r94521:ef3c287b0add
Date: 2018-05-11 12:55 +0200
http://bitbucket.org/pypy/pypy/changeset/ef3c287b0add/

Log:    don't crash if the locals aren't a dict. fix another corner case
        about annotations.

        (aside: this shows that removing the _settled_ = True feature was
        not a good idea, as it would have caught this bug)

diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -849,7 +849,7 @@
             if not e.match(self.space, self.space.w_KeyError):
                 raise
             raise oefmt(self.space.w_NameError,
-                        "name %R is not defined", w_varname)
+                        "__annotations__ not found")
 
     def UNPACK_SEQUENCE(self, itemcount, next_instr):
         w_iterable = self.popvalue()
@@ -958,10 +958,17 @@
             self.space.setitem_str(w_locals, '__annotations__', w_annotations)
 
     def STORE_ANNOTATION(self, varindex, next_instr):
+        space = self.space
         varname = self.getname_u(varindex)
         w_newvalue = self.popvalue()
-        
self.space.setitem_str(self.getorcreatedebug().w_locals.getitem_str('__annotations__'),
 varname,
-                               w_newvalue)
+        w_locals = self.getorcreatedebug().w_locals
+        try:
+            w_annotations = space.getitem(w_locals, 
space.newtext('__annotations__'))
+        except OperationError as e:
+            if e.match(space, space.w_KeyError):
+                raise oefmt(space.w_NameError, CANNOT_CATCH_MSG)
+            raise
+        self.space.setitem_str(w_annotations, varname, w_newvalue)
 
     def BUILD_TUPLE(self, itemcount, next_instr):
         items = self.popvalues(itemcount)
diff --git a/pypy/interpreter/test/test_annotations.py 
b/pypy/interpreter/test/test_annotations.py
--- a/pypy/interpreter/test/test_annotations.py
+++ b/pypy/interpreter/test/test_annotations.py
@@ -111,3 +111,24 @@
             except:
                 assert False
         '''
+
+    def test_locals_arent_dicts(self):
+        class O:
+            def __init__(self):
+                self.dct = {}
+            def __getitem__(self, name):
+                return self.dct[name]
+            def __setitem__(self, name, value):
+                self.dct[name] = value
+        # don't crash if locals aren't just a normal dict
+        exec("a: int; assert __annotations__['a'] == int", {}, O())
+
+    def test_NameError_if_annotations_are_gone(self):
+        exec("""if 1:
+            raises(NameError, '''if 1:
+                class A:
+                    del __annotations__
+                    a: int
+            ''')
+        """)
+
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to