Re: [Python-Dev] sys.settrace: behavior doesn't match docs

2011-05-02 Thread Nick Coghlan
On Mon, May 2, 2011 at 10:47 PM, Mark Hammond  wrote:
> On 2/05/2011 9:27 PM, Ned Batchelder wrote:
> ...
>>
>> Maybe the fact no one noticed the docs
>> were wrong proves that no one ever tried returning None from a local
>> trace function.
>
> Or if they did, they should have complained by now.  IMO, if the behaviour
> regresses from how it is documented and how it previously worked and no
> reports of the regression exist, we should just fix it without regard to
> people relying on the "new" functionality...

+1

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] sys.settrace: behavior doesn't match docs

2011-05-02 Thread Mark Hammond

On 2/05/2011 9:27 PM, Ned Batchelder wrote:
...

Maybe the fact no one noticed the docs
were wrong proves that no one ever tried returning None from a local
trace function.


Or if they did, they should have complained by now.  IMO, if the 
behaviour regresses from how it is documented and how it previously 
worked and no reports of the regression exist, we should just fix it 
without regard to people relying on the "new" functionality...


Mark
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] sys.settrace: behavior doesn't match docs

2011-05-02 Thread Ned Batchelder

Indeed, the 2.0 code is very different, and got this case right.

I'm a little surprised no one is arguing that changing this code now 
could break some applications.  Maybe the fact no one noticed the docs 
were wrong proves that no one ever tried returning None from a local 
trace function.


--Ned.

On 4/30/2011 8:43 PM, Guido van Rossum wrote:

I think you need to go back farther in time. :-) In Python 2.0 the
call_trace function in ceval.c has a completely different signature
(but the docs are the same). I haven't checked all history but
somewhere between 2.0 and 2.3, SET_LINENO-less tracing was added, and
that's where the implementation must have gone wrong. So I think we
should fix the code.

--Guido

On Sat, Apr 30, 2011 at 3:49 PM, Ned Batchelder  wrote:

This week I learned something new about trace functions (how to write a C
trace function that survives a sys.settrace(sys.gettrace()) round-trip), and
while writing up what I learned, I was surprised to discover that trace
functions don't behave the way I thought, or the way the docs say they
behave.

The docs say:

The trace function is invoked (with event set to 'call') whenever a new
local scope is entered; it should return a reference to a local trace
function to be used that scope, or None if the scope shouldn’t be traced.

The local trace function should return a reference to itself (or to another
function for further tracing in that scope), or None to turn off tracing in
that scope.

It's that last part that's wrong: returning None from the trace function
only has an effect on the first call in a new frame.  Once the trace
function returns a function for a frame, returning None from subsequent
calls is ignored.  A "local trace function" can't turn off tracing in its
scope.

To demonstrate:

import sys

UPTO_LINE = 1

def t(frame, event, arg):
 num = frame.f_lineno
 print("line %d" % num)
 if num<  UPTO_LINE:
 return t

def try_it():
 print("twelve")
 print("thirteen")
 print("fourteen")
 print("fifteen")

UPTO_LINE = 1
sys.settrace(t)
try_it()

UPTO_LINE = 13
sys.settrace(t)
try_it()

Produces:

line 11
twelve
thirteen
fourteen
fifteen
line 11
line 12
twelve
line 13
thirteen
line 14
fourteen
line 15
fifteen
line 15

The first call to try_it() returns None immediately, preventing tracing for
the rest of the function.  The second call returns None at line 13, but the
rest of the function is traced anyway.  This behavior is the same in all
versions from 2.3 to 3.2, in fact, the 100 lines of code in sysmodule.c
responsible for Python tracing functions are completely unchanged through
those versions.  (A deeper mystery that I haven't looked into yet is why
Python 3.x intersperses all of these lines with "line 18" interjections.)

I'm writing this email because I'm not sure whether this is a behavior bug
or a doc bug.  One of them is wrong, since they disagree.  The documented
behavior makes sense, and is what people have all along thought the trace
function did.  The actual behavior is a bit more complicated to explain, but
is what people have actually been experiencing.  FWIW, PyPy implements the
documented behavior.

Should we fix the code or the docs?  I'd be glad to supply a patch for
either.

--Ned.


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
http://mail.python.org/mailman/options/python-dev/guido%40python.org






___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] sys.settrace: behavior doesn't match docs

2011-04-30 Thread Guido van Rossum
I think you need to go back farther in time. :-) In Python 2.0 the
call_trace function in ceval.c has a completely different signature
(but the docs are the same). I haven't checked all history but
somewhere between 2.0 and 2.3, SET_LINENO-less tracing was added, and
that's where the implementation must have gone wrong. So I think we
should fix the code.

--Guido

On Sat, Apr 30, 2011 at 3:49 PM, Ned Batchelder  wrote:
> This week I learned something new about trace functions (how to write a C
> trace function that survives a sys.settrace(sys.gettrace()) round-trip), and
> while writing up what I learned, I was surprised to discover that trace
> functions don't behave the way I thought, or the way the docs say they
> behave.
>
> The docs say:
>
> The trace function is invoked (with event set to 'call') whenever a new
> local scope is entered; it should return a reference to a local trace
> function to be used that scope, or None if the scope shouldn’t be traced.
>
> The local trace function should return a reference to itself (or to another
> function for further tracing in that scope), or None to turn off tracing in
> that scope.
>
> It's that last part that's wrong: returning None from the trace function
> only has an effect on the first call in a new frame.  Once the trace
> function returns a function for a frame, returning None from subsequent
> calls is ignored.  A "local trace function" can't turn off tracing in its
> scope.
>
> To demonstrate:
>
> import sys
>
> UPTO_LINE = 1
>
> def t(frame, event, arg):
>     num = frame.f_lineno
>     print("line %d" % num)
>     if num < UPTO_LINE:
>     return t
>
> def try_it():
>     print("twelve")
>     print("thirteen")
>     print("fourteen")
>     print("fifteen")
>
> UPTO_LINE = 1
> sys.settrace(t)
> try_it()
>
> UPTO_LINE = 13
> sys.settrace(t)
> try_it()
>
> Produces:
>
> line 11
> twelve
> thirteen
> fourteen
> fifteen
> line 11
> line 12
> twelve
> line 13
> thirteen
> line 14
> fourteen
> line 15
> fifteen
> line 15
>
> The first call to try_it() returns None immediately, preventing tracing for
> the rest of the function.  The second call returns None at line 13, but the
> rest of the function is traced anyway.  This behavior is the same in all
> versions from 2.3 to 3.2, in fact, the 100 lines of code in sysmodule.c
> responsible for Python tracing functions are completely unchanged through
> those versions.  (A deeper mystery that I haven't looked into yet is why
> Python 3.x intersperses all of these lines with "line 18" interjections.)
>
> I'm writing this email because I'm not sure whether this is a behavior bug
> or a doc bug.  One of them is wrong, since they disagree.  The documented
> behavior makes sense, and is what people have all along thought the trace
> function did.  The actual behavior is a bit more complicated to explain, but
> is what people have actually been experiencing.  FWIW, PyPy implements the
> documented behavior.
>
> Should we fix the code or the docs?  I'd be glad to supply a patch for
> either.
>
> --Ned.
>
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> http://mail.python.org/mailman/options/python-dev/guido%40python.org
>
>



-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] sys.settrace: behavior doesn't match docs

2011-04-30 Thread Ned Batchelder
This week I learned something new about trace functions (how to write a 
C trace function that survives a sys.settrace(sys.gettrace()) 
round-trip), and while writing up what I learned, I was surprised to 
discover that trace functions don't behave the way I thought, or the way 
the docs say they behave.


The docs say:

   The trace function is invoked (with /event/ set to 'call') whenever
   a new local scope is entered; it should return a reference to a
   local trace function to be used that scope, or None if the scope
   shouldn't be traced.

   The local trace function should return a reference to itself (or to
   another function for further tracing in that scope), or None to turn
   off tracing in that scope.

It's that last part that's wrong: returning None from the trace function 
only has an effect on the first call in a new frame.  Once the trace 
function returns a function for a frame, returning None from subsequent 
calls is ignored.  A "local trace function" can't turn off tracing in 
its scope.


To demonstrate:

   import sys

   UPTO_LINE = 1

   def t(frame, event, arg):
num = frame.f_lineno
print("line %d" % num)
if num < UPTO_LINE:
return t

   def try_it():
print("twelve")
print("thirteen")
print("fourteen")
print("fifteen")

   UPTO_LINE = 1
   sys.settrace(t)
   try_it()

   UPTO_LINE = 13
   sys.settrace(t)
   try_it()

Produces:

   line 11
   twelve
   thirteen
   fourteen
   fifteen
   line 11
   line 12
   twelve
   line 13
   thirteen
   line 14
   fourteen
   line 15
   fifteen
   line 15

The first call to try_it() returns None immediately, preventing tracing 
for the rest of the function.  The second call returns None at line 13, 
but the rest of the function is traced anyway.  This behavior is the 
same in all versions from 2.3 to 3.2, in fact, the 100 lines of code in 
sysmodule.c responsible for Python tracing functions are completely 
unchanged through those versions.  (A deeper mystery that I haven't 
looked into yet is why Python 3.x intersperses all of these lines with 
"line 18" interjections.)


I'm writing this email because I'm not sure whether this is a behavior 
bug or a doc bug.  One of them is wrong, since they disagree.  The 
documented behavior makes sense, and is what people have all along 
thought the trace function did.  The actual behavior is a bit more 
complicated to explain, but is what people have actually been 
experiencing.  FWIW, PyPy implements the documented behavior.


Should we fix the code or the docs?  I'd be glad to supply a patch for 
either.


--Ned.


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com