Repository: alexmojaki/snoop (language: python)

Issue:
Detecting re-entering generator broken in 3.11
Noticed in https://github.com/alexmojaki/snoop/pull/55


Discussion / hints:

Fix patch:
diff --git a/snoop/formatting.py b/snoop/formatting.py
index c2ff097..2919e67 100644
--- a/snoop/formatting.py
+++ b/snoop/formatting.py
@@ -155,13 +155,23 @@ def source_line(self):
     def code_qualname(self):
         return self.source.code_qualname(self.code)
 
-    @property
-    def opname(self):
-        code_byte = self.code.co_code[self.frame.f_lasti]
+    def opname_at(self, index):
+        code_byte = self.code.co_code[index]
         if not isinstance(code_byte, int):
             code_byte = ord(code_byte)
         return opcode.opname[code_byte]
 
+    @property
+    def opname(self):
+        return self.opname_at(self.frame.f_lasti)
+
+    @property
+    def is_yield_value(self):
+        for i in range(self.frame.f_lasti, -1, -1):
+            opname = self.opname_at(i)
+            if opname not in ('RESUME', 'CACHE'):
+                return opname == 'YIELD_VALUE'
+
 
 class DefaultFormatter(object):
     datetime_format = None
@@ -358,7 +368,7 @@ def format_start(self, event):
             else:
                 assert event.event == 'call'
                 if event.frame_info.is_generator:
-                    if event.opname == 'YIELD_VALUE':
+                    if event.is_yield_value:
                         description = 'Re-enter generator'
                     else:
                         description = 'Start generator'


Test patch:
diff --git a/tests/sample_results/3.11/generator.txt b/tests/sample_results/3.11/generator.txt
index 7f2ee09..542d83d 100644
--- a/tests/sample_results/3.11/generator.txt
+++ b/tests/sample_results/3.11/generator.txt
@@ -4,7 +4,7 @@
 12:34:56.78   13 |     assert not original_tracer_active()
 12:34:56.78   14 |     _x2 = (yield x1)
 12:34:56.78 <<< Yield value from f: 0
-12:34:56.78 >>> Start generator f in File "/path/to_file.py", line 14
+12:34:56.78 >>> Re-enter generator f in File "/path/to_file.py", line 14
 12:34:56.78 .......... x1 = 0
 12:34:56.78   14 |     _x2 = (yield x1)
 12:34:56.78 .......... _x2 = 'blabla'
@@ -13,7 +13,7 @@
 12:34:56.78   17 |     assert not original_tracer_active()
 12:34:56.78   18 |     _x4 = (yield 2)
 12:34:56.78 <<< Yield value from f: 2
-12:34:56.78 >>> Start generator f in File "/path/to_file.py", line 18
+12:34:56.78 >>> Re-enter generator f in File "/path/to_file.py", line 18
 12:34:56.78 .......... x1 = 0
 12:34:56.78 .......... _x2 = 'blabla'
 12:34:56.78 .......... _x3 = 'foo'
diff --git a/tests/sample_results/3.11/generator_expression.txt b/tests/sample_results/3.11/generator_expression.txt
index 8259cbb..8c4fa77 100644
--- a/tests/sample_results/3.11/generator_expression.txt
+++ b/tests/sample_results/3.11/generator_expression.txt
@@ -7,13 +7,13 @@
     12:34:56.78 .......... Iterating over <tupleiterator object at 0xABC>
     12:34:56.78 .......... x = 1
     12:34:56.78 <<< Yield value from <genexpr>: 2
-    12:34:56.78 >>> Start generator <genexpr> in File "/path/to_file.py", line 6
+    12:34:56.78 >>> Re-enter generator <genexpr> in File "/path/to_file.py", line 6
     12:34:56.78    6 |     return list(x * 2 for x in [1, 2])
     12:34:56.78    6 |     return list(x * 2 for x in [1, 2])
     12:34:56.78 .......... Iterating over <tupleiterator object at 0xABC>
     12:34:56.78 .......... x = 2
     12:34:56.78 <<< Yield value from <genexpr>: 4
-    12:34:56.78 >>> Start generator <genexpr> in File "/path/to_file.py", line 6
+    12:34:56.78 >>> Re-enter generator <genexpr> in File "/path/to_file.py", line 6
     12:34:56.78    6 |     return list(x * 2 for x in [1, 2])
     12:34:56.78    6 |     return list(x * 2 for x in [1, 2])
     12:34:56.78 .......... Iterating over <tupleiterator object at 0xABC>
diff --git a/tests/sample_results/3.11/with_block.txt b/tests/sample_results/3.11/with_block.txt
index 51b2117..2abbc8b 100644
--- a/tests/sample_results/3.11/with_block.txt
+++ b/tests/sample_results/3.11/with_block.txt
@@ -45,7 +45,7 @@
 12:34:56.78 .................. i = 1
 12:34:56.78   48 |                 yield i
 12:34:56.78 <<< Yield value from gen: 1
-12:34:56.78 >>> Start generator gen in File "/path/to_file.py", line 48
+12:34:56.78 >>> Re-enter generator gen in File "/path/to_file.py", line 48
 12:34:56.78 ...................... i = 1
 12:34:56.78   48 |                 yield i
 12:34:56.78   47 |             with snoop:
diff --git a/tests/version_differences.txt b/tests/version_differences.txt
index 6724eb5..281e094 100644
--- a/tests/version_differences.txt
+++ b/tests/version_differences.txt
@@ -48,16 +48,6 @@ pypy2.7, pypy3.5, pypy3.6
 f_string
 Doesn't exist: 2.7, 3.4, 3.5, pypy2.7, pypy3.5
 
-generator
-Differing versions:
-2.7, 3.10, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, pypy2.7, pypy3.5, pypy3.6
-3.11
-
-generator_expression
-Differing versions:
-2.7, 3.10, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, pypy2.7, pypy3.5, pypy3.6
-3.11
-
 multiline
 Differing versions:
 2.7, 3.4, 3.5, 3.6, 3.7, pypy2.7, pypy3.5, pypy3.6
@@ -97,8 +87,7 @@ Differing versions:
 with_block
 Differing versions:
 2.7, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, pypy2.7, pypy3.5, pypy3.6
-3.10
-3.11
+3.10, 3.11
 
 with_block_depth
 Differing versions: