[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