-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
Certain sys.monitoring "not taken" branches in a for
loop not showing correctly
#123050
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
There's a few things going on here.
Conceptually the this is a single instruction:
We need to account for We don't want to prevent the compiler from generating efficient code, so we needs a means to handle these complex cases, so we'll need to handle this Since this isn't bug until we add the new branch events, I'm marking this as a feature request. |
Updating the disassembly for the current code in pull/122564; the branches around the
|
Latest disassembly (with offsets) on main:
I don't know why the The branch from 22 to L2 (32) jumps to an instruction with no line number, but execution will immediately proceed to 34 (line 4). |
On latest main the disassembly now looks like this:
And the branches: >>> list(foo.__code__.co_branches())
[(6, 10, 48), (20, 26, 30)] which, to me, looks correct. |
Hi @markshannon, thank you. That 20->26 branch maps the same location in source and destination,
which I think we previously said means an exit from the function? Anyway, I have been increasingly thinking that we may be asking for too much... we could maybe just report on the number of branches taken/existing per line, and give up on filtering out clause branches. @nedbat, what do you think? |
BTW, I missed initializing def foo():
x = 0
for v in [1, 2]:
if v > 0:
x += v
return x If we continue on this, let's please use this version instead. |
I don't know what this means. It feels like we are close to getting the data we want. |
I mean filtering out the branches such as the one between the |
@nedbat @jaltmayerpizzorno |
I still am getting a branch whose destination maps back to the same portion of code... Using the code in 'main' (c6513f7), I get:
This is, as before, using All branches but the 3rd are fairly clear. The 3rd branch, from 24 to 30, is really 4->3... there's no |
@jaltmayerpizzorno are there some typos in your description? I think we have the information we need. Coverage.py now follows trails of instructions until a new line is reached. Here is what I see for the disassembly, and how the latest coverage.py code interprets it:
The possible branch points are instructions with jump targets that aren't unconditional jumps: offsets 10 and 24.
Final result is line 3 branches to either 4 or 7, and line 4 branches to 3 or 5. |
Quite possibly, but I don't see them... If you are referring to the tuples showing the branches, that is simply
I tried that method for finding out the branch destinations for SlipCover (years ago) and found it unreliable... Essentially, I'd:
When do we stop tracking the bytecode, though? Stopping when you reach a new line works well for things like skipping over a if x: f() Also, while tracking, what do we do about conditional jump opcodes? Do we stop there? Do we ignore them? Or do we track both branches and extract the destination somehow from the (potentially various) resulting paths? I think ideally we wouldn't trace the code at all, but instead rely on a given mapping ( |
I thought I should clarify what I'm saying. As @nedbat shared, he coded a mechanism that enumerates branches and deduces their destination by stepping through bytecode. I understand that he is satisfied that it works well enough for Coverage.py, and that's great! Seriously. I just don't think coding something like that should be necessary to fully utilize I don't know if using |
Bug report
Bug description:
With the code from PR 122564, the destinations of the "not taken" branches out of lines 2 and 3 show as going out of scope, rather than the correct line 6. Additionally, the ("taken") branch into
if
's block also shows as going out of scope:Results:
@markshannon @nedbat
CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
The text was updated successfully, but these errors were encountered: