[New-bugs-announce] [issue44626] Incorrect tracing of nested if/if/for/yield

Ned Batchelder report at bugs.python.org
Tue Jul 13 14:23:06 EDT 2021


New submission from Ned Batchelder <ned at nedbatchelder.com>:

In Python 3.10, this code is traced incorrectly. I don't know if there's a simpler format that would show the problem. This code is already simplified from https://github.com/nedbat/coveragepy/issues/1188.

------------------------------
import linecache, sys

def trace(frame, event, arg):
    # The weird globals here is to avoid a NameError on shutdown...
    if frame.f_code.co_filename == globals().get("__file__"):
        lineno = frame.f_lineno
        print("{} {}: {}".format(event[:4], lineno, linecache.getline(__file__, lineno).rstrip()))
    return trace

print(sys.version)
sys.settrace(trace)

def f(a, p, z):
    if p:
        print(f"{a=}")
        if a:
            if z:
                for x in [1,2]:
                    yield x
            else:
                for x in [1,2]:
                    yield x
    else:
        print("nope")

import itertools

for a, p, z in itertools.product([0, 1], repeat=3):
    list(f(a, p, z))
------------------------------------

Running this with 3.10.0b4 produces this output. The starred lines show a is false, but tracing then indicates a line which is not executed:

  3.10.0b4 (default, Jul 11 2021, 13:51:53) [Clang 12.0.0 (clang-1200.0.32.29)]
  call 13: def f(a, p, z):
  line 14:     if p:
  line 24:         print("nope")
  nope
  retu 24:         print("nope")
  call 13: def f(a, p, z):
  line 14:     if p:
  line 24:         print("nope")
  nope
  retu 24:         print("nope")
  call 13: def f(a, p, z):
  line 14:     if p:
  line 15:         print(f"{a=}")
  a=0
* line 16:         if a:
  line 22:                     yield x
  retu 22:                     yield x
  call 13: def f(a, p, z):
  line 14:     if p:
  line 15:         print(f"{a=}")
  a=0
* line 16:         if a:
  line 22:                     yield x
  retu 22:                     yield x
  call 13: def f(a, p, z):
  line 14:     if p:
  line 24:         print("nope")
  nope
  retu 24:         print("nope")
  call 13: def f(a, p, z):
  line 14:     if p:
  line 24:         print("nope")
  nope
  retu 24:         print("nope")
  call 13: def f(a, p, z):
  line 14:     if p:
  line 15:         print(f"{a=}")
  a=1
  line 16:         if a:
  line 17:             if z:
  line 21:                 for x in [1,2]:
  line 22:                     yield x
  retu 22:                     yield x
  call 22:                     yield x
  line 21:                 for x in [1,2]:
  line 22:                     yield x
  retu 22:                     yield x
  call 22:                     yield x
  line 21:                 for x in [1,2]:
  line 22:                     yield x
  retu 22:                     yield x
  call 13: def f(a, p, z):
  line 14:     if p:
  line 15:         print(f"{a=}")
  a=1
  line 16:         if a:
  line 17:             if z:
  line 18:                 for x in [1,2]:
  line 19:                     yield x
  retu 19:                     yield x
  call 19:                     yield x
  line 18:                 for x in [1,2]:
  line 19:                     yield x
  retu 19:                     yield x
  call 19:                     yield x
  line 18:                 for x in [1,2]:
  retu 18:                 for x in [1,2]:

----------
components: Interpreter Core
keywords: 3.10regression
messages: 397434
nosy: Mark.Shannon, nedbat
priority: normal
severity: normal
status: open
title: Incorrect tracing of nested if/if/for/yield
type: behavior
versions: Python 3.10

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue44626>
_______________________________________


More information about the New-bugs-announce mailing list