2011-07-29 08:26:52 +04:00
#!/usr/bin/env python
"""
This file shows how you can define a custom stringifier for PuDB .
A stringifier is a function that is called on the variables in the namespace
for display in the variables list . The default is type ( ) * , as this is fast and
cannot fail . PuDB also includes built - in options for using str ( ) and repr ( ) .
Note that str ( ) and repr ( ) will be slower than type ( ) , which is especially
noticable when you have many varialbes , or some of your variables have very
large string / repr representations .
Also note that if you just want to change the type for one or two variables ,
you can do that by selecting the variable in the variables list and pressing
Enter , or by pressing t , s , or r .
To define a custom stringifier , create a file like this one with a function
called pudb_stringifier ( ) at the module level . pudb_stringifier ( obj ) should
return a string value for an object ( note that str ( ) will always be called on
the result ) . Note that the file will be execfile ' d.
Then , go to the PuDB preferences window ( type Ctrl - p inside of
PuDB ) , and add the path to the file in the " Custom " field under the " Variable
Stringifier " heading.
2011-08-09 14:13:17 +04:00
The example in this file returns the string value , unless it take more than 500
ms ( 1 second in Python 2.5 - ) to compute , in which case it falls back to the
type .
2011-07-29 08:26:52 +04:00
TIP : Run " python -m pudb.run example-stringifier.py and set this file to be
your stringifier in the settings to see how it works .
You can use custom stringifiers to do all sorts of things : callbacks , custom
views on variables of interest without having to use a watch variable or the
expanded view , etc .
* - Actually , the default is a mix between type ( ) and str ( ) . str ( ) is used for
a handful of " safe " types for which it is guaranteed to be fast and not to
fail .
"""
import time
import signal
2011-08-09 14:13:17 +04:00
import sys
import math
2011-07-29 08:26:52 +04:00
class TimeOutError ( Exception ) :
pass
def timeout ( signum , frame , time ) :
raise TimeOutError ( " Timed out after %d seconds " % time )
def run_with_timeout ( code , time , globals = None ) :
"""
Evaluate ` ` code ` ` , timing out after ` ` time ` ` seconds .
2011-08-09 15:22:50 +04:00
In Python 2.5 and lower , ` ` time ` ` is rounded up to the nearest integer .
The return value is whatever ` ` code ` ` returns .
2011-07-29 08:26:52 +04:00
"""
# Set the signal handler and a ``time``-second alarm
signal . signal ( signal . SIGALRM , lambda s , f : timeout ( s , f , time ) )
2011-08-09 14:13:17 +04:00
if sys . version_info > ( 2 , 5 ) :
signal . setitimer ( signal . ITIMER_REAL , time )
else :
# The above only exists in Python 2.6+
# Otherwise, we have to use this, which only supports integer arguments
# Use math.ceil to round a float up.
time = int ( math . ceil ( time ) )
signal . alarm ( time )
2011-07-29 08:26:52 +04:00
r = eval ( code , globals )
signal . alarm ( 0 ) # Disable the alarm
return r
def pudb_stringifier ( obj ) :
"""
This is the custom stringifier .
It returns str ( obj ) , unless it take more than a second to compute ,
in which case it falls back to type ( obj ) .
"""
try :
2011-08-09 14:13:17 +04:00
return run_with_timeout ( " str(obj) " , 0.5 , { ' obj ' : obj } )
2011-07-29 08:26:52 +04:00
except TimeOutError :
return ( type ( obj ) , " (str too slow to compute) " )
# Example usage
class FastString ( object ) :
def __str__ ( self ) :
return " This was fast to compute. "
class SlowString ( object ) :
def __str__ ( self ) :
time . sleep ( 10 ) # Return the string value after ten seconds
return " This was slow to compute. "
fast = FastString ( )
slow = SlowString ( )
2011-07-29 08:35:56 +04:00
# If you are running this in PuDB, set this file as your custom stringifier in
# the prefs (Ctrl-p) and run to here. Notice how fast shows the string value,
# but slow shows the type, as the string value takes too long to compute.