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