[Python-Dev] seeing off SET_LINENO

Michael Hudson mwh@python.net
02 Aug 2002 11:34:55 +0100


Guido van Rossum <guido@python.org> writes:

> What's the next step?  I haven't had time to review your code.  Do you
> want to check it in without further review, or do you want to wait
> until someone can give it a serious look?  (Tim's on vacation this
> week so it might be a while.)

I've found another annoying problem.  I'm not really expecting someone
here to sovle it for me, but writing it down might help me think
clearly.

This is about the function epilogues that always get generated.  I.e:

>>> def f():
...     if a:
...         print 1
... 
>>> import dis
>>> dis.dis(f)
  2           0 LOAD_GLOBAL              0 (a)
              3 JUMP_IF_FALSE            9 (to 15)
              6 POP_TOP             

  3           7 LOAD_CONST               1 (1)
             10 PRINT_ITEM          
             11 PRINT_NEWLINE       
             12 JUMP_FORWARD             1 (to 16)
        >>   15 POP_TOP             
        >>   16 LOAD_CONST               0 (None)
             19 RETURN_VALUE        

You can see here that the epilogue gets associated with line 3,
whereas it shouldn't really be associated with any line at all.

For why this is a problem:

$ cat t.py
a = 0
def f():
    if a:
        print 1

>>> pdb.runcall(t.f)
> /home/mwh/src/sf/python/dist/src/build/t.py(3)f()
-> if a:
(Pdb) s
> /home/mwh/src/sf/python/dist/src/build/t.py(4)f()
-> print 1
(Pdb) 
--Return--
> /home/mwh/src/sf/python/dist/src/build/t.py(4)f()->None
-> print 1
(Pdb) 

The debugger stopping on the "print 1" is confusing.

There's an "obvious" solution to this: check it we're less than 4
bytes from the end of the code string and don't do anything if we are.
This would be easy, except that for some bonkers reason, we support
arbitrary buffer objects for code strings!  (see _PyCode_GETCODEPTR in
Include/compile.h -- though at least you can't create a code object
with an array code string from python, the getreadbuffer failing will
cause the interpreter to unceremoniously crash and burn).

I guess I can store the length somewhere -- _PyCode_GETCODEPTR returns
this, more by accident than design I suspect -- or call
bf_getsegcount(frame->f_code->co_code, &length) or something.

Does anyone actually *use* this feature?  I see Guido checked it in
and the patch was written by Greg Stein.  Anyone remember motivations
from the time?

Cheers,
M.

-- 
  In general, I'd recommend injecting LSD directly into your temples,
  Syd-Barret-style, before mucking with Motif's resource framework.
  The former has far lower odds of leading directly to terminal
  insanity.                                            -- Dan Martinez