[pypy-commit] pypy py3.6: Evaluate target only once when doing an annotated setitem
rlamy
pypy.commits at gmail.com
Mon Nov 11 09:18:04 EST 2019
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.6
Changeset: r98026:7d21b9cbf13a
Date: 2019-11-11 14:17 +0000
http://bitbucket.org/pypy/pypy/changeset/7d21b9cbf13a/
Log: Evaluate target only once when doing an annotated setitem
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -1008,11 +1008,12 @@
attr = target.value
self._annotation_evaluate(attr)
elif isinstance(target, ast.Subscript):
- # similar to the above, `a[0:5]: int` evaluates the name and the slice argument
- # and if not in a function, also evaluates the annotation
- sl = target.slice
- self._annotation_evaluate(target.value)
- self._annotation_eval_slice(sl)
+ if not assign.value:
+ # similar to the above, `a[0:5]: int` evaluates the name and the slice argument
+ # and if not in a function, also evaluates the annotation
+ sl = target.slice
+ self._annotation_evaluate(target.value)
+ self._annotation_eval_slice(sl)
else:
self.error("can't handle annotation with %s" % (target,), target)
# if this is not in a function, evaluate the annotation
diff --git a/pypy/interpreter/test/apptest_annotations.py b/pypy/interpreter/test/apptest_annotations.py
--- a/pypy/interpreter/test/apptest_annotations.py
+++ b/pypy/interpreter/test/apptest_annotations.py
@@ -56,12 +56,8 @@
C()
def test_nonexistent_target():
- try:
- # this is invalid because `y` is undefined
- # it should raise a NameError
+ with pytest.raises(NameError):
y[0]: invalid
- except NameError:
- ...
def test_non_simple_func_annotation():
a = 5
@@ -136,3 +132,36 @@
assert C.__annotations__ == {"cls": "abc"}
f("abc")
+
+def test_side_effects():
+ calls = 0
+ def foo():
+ nonlocal calls
+ calls += 1
+ foo()
+ assert calls == 1
+ exec("foo()")
+ assert calls == 2
+ d = {}
+ exec("a: foo() = 1")
+ exec("b: foo()")
+ assert calls == 4
+ c = None
+ exec("c[foo()]: int")
+ assert calls == 5
+ def g():
+ c = None
+ c[foo()]: int
+ assert calls == 5
+ g()
+ assert calls == 6
+
+def test_side_effects_2():
+ calls = 0
+ def foo():
+ nonlocal calls
+ calls += 1
+ d = {}
+ exec("d[foo()]: int = 1")
+ assert d[None] == 1
+ assert calls == 1
More information about the pypy-commit
mailing list