]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/tools/dbg.py
   1 #---------------------------------------------------------------------------- 
   5 # Email:        wsadkin@nameconnector.com 
   7 # Copyright:    (c) 2002 by Will Sadkin, 2002 
   8 # License:      wxWindows license 
   9 #---------------------------------------------------------------------------- 
  10 # 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net) 
  12 # o V2.5 compatability update  
  16 This module provides a useful debugging framework that supports 
  17 showing nesting of function calls and allows a program to contain 
  18 lots of debugging print statements that can easily be turned on 
  19 or off to debug the code.  It also supports the ability to 
  20 have each function indent the debugging statements contained 
  21 within it, including those of any other function called within 
  22 its scope, thus allowing you to see in what order functions are 
  23 being called, and from where. 
  25 This capability is particularly useful in wxPython applications, 
  26 where exactly events occur that cause functions to be called is 
  27 not entirely clear, and because wxPython programs can't be run 
  28 from inside other debugging environments that have their own 
  31 This module defines a Logger class, responsible for managing 
  32 debugging output.  Each Logger instance can be given a name 
  33 at construction; if this is done, '<name>:' will precede each 
  34 logging output made by that Logger instance. 
  36 The log() function this class provides takes a set of positional 
  37 arguments that are printed in order if debugging is enabled 
  38 (just like print does), followed by a set of keyword arguments 
  39 that control the behavior of the log() function itself on subsequent 
  40 calls.  The current keyword arguments are: 
  43     When set to a value of 1, this increments the current 
  44     indentation level, causing all subsequent dbg() outputs to be 
  45     indented by 3 more spaces.  When set to a value of 0, 
  46     this process is reversed, causing the indent to decrease by 
  47     3 spaces.  The default indentation level is 0. 
  50     When set to a value of 1, this turns on dbg() output for 
  51     for program importing this module, until told to do otherwise. 
  52     When set to a value of 0, dbg output is turned off.  (dbg 
  53     output is off by default.) 
  56     When set to a value of 1, this increments the current 
  57     "suspension" level.  This makes it possible for a function 
  58     to temporarily suspend its and any of its dependents' 
  59     potential outputs that use the same Logger instance. 
  60     When set to a value of 0, the suspension level is 
  61     decremented.  When the value goes back to 0, potential 
  62     logging is resumed (actual output depends on the 
  63     "enable" status of the Logger instance in question.) 
  66     When set to a value of 1, the output will be sent to the 
  70     When set to a non-None value, the current output stream 
  71     (default of sys.stdout) is pushed onto a stack of streams, 
  72     and is replaced in the dbg system with the specified stream. 
  73     When called with a value of None, the previous stream will 
  74     be restored (if stacked.)  If set to None without previously 
  75     changing it will result in no action being taken. 
  77 You can also call the log function implicitly on the Logger 
  78 instance, ie. you can type:: 
  80     from wxPython.tools.dbg import Logger 
  82     dbg('something to print') 
  84 Using this fairly simple mechanism, it is possible to get fairly 
  85 useful debugging output in a program.  Consider the following 
  88 >>> d = {1:'a', 2:'dictionary', 3:'of', 4:'words'} 
  89 >>> dbg = dbg.Logger('module') 
  93 ...     dbg('foo', indent=1) 
  95 ...     dbg('end of foo', indent=0) 
  98 ...     dbg('bar', indent=1) 
  99 ...     dbg('contents of d:', indent=1) 
 102 ...     for key, value in l: 
 103 ...         dbg('%d =' % key, value) 
 105 ...     dbg('end of bar', indent=0) 
 110       module: contents of d: 
 112          module: 2 = dictionary 
 123     def __init__(self
, name
=None): 
 126         self
._indent 
= 0     # current number of indentations 
 127         self
._dbg 
= 0        # enable/disable flag 
 128         self
._suspend 
= 0    # allows code to "suspend/resume" potential dbg output 
 129         self
._wxLog 
= 0      # use wxLogMessage for debug output 
 130         self
._outstream 
= sys
.stdout  
# default output stream 
 131         self
._outstream
_stack 
= []    # for restoration of streams as necessary 
 141     def log(self
, *args
, **kwargs
): 
 143         This function provides a useful framework for generating 
 144         optional debugging output that can be displayed at an 
 145         arbitrary level of indentation. 
 147         if not self
._dbg 
and not 'enable' in kwargs
.keys(): 
 150         if self
._dbg 
and len(args
) and not self
._suspend
: 
 151             # (emulate print functionality; handle unicode as best as possible:) 
 155                     strs
.append(str(arg
)) 
 157                     strs
.append(repr(arg
)) 
 159             output 
= ' '.join(strs
) 
 160             if self
.name
: output 
= self
.name
+': ' + output
 
 161             output 
= ' ' * 3 * self
._indent 
+ output
 
 164                 from wxPython
.wx 
import wxLogMessage    
# (if not already imported) 
 167                 self
._outstream
.write(output 
+ '\n') 
 168                 self
._outstream
.flush() 
 172         for kwarg
, value 
in kwargs
.items(): 
 173             if kwarg 
== 'indent': 
 174                 self
.SetIndent(value
) 
 175             elif kwarg 
== 'enable': 
 176                 self
.SetEnabled(value
) 
 177             elif kwarg 
== 'suspend': 
 178                 self
.SetSuspend(value
) 
 179             elif kwarg 
== 'wxlog': 
 181             elif kwarg 
== 'stream': 
 182                 self
.SetStream(value
) 
 184     # aliases for the log function 
 185     dbg 
= log       
# backwards compatible 
 187     __call__ 
= log  
# this one lets you 'call' the instance directly 
 190     def SetEnabled(self
, value
): 
 195                 self
.dbg('dbg enabled') 
 198                 self
.dbg('dbg disabled') 
 202     def SetSuspend(self
, value
): 
 205         elif self
._suspend 
> 0: 
 209     def SetIndent(self
, value
): 
 212         elif self
._indent 
> 0: 
 216     def SetWxLog(self
, value
): 
 220     def SetStream(self
, value
): 
 222             self
._outstream
_stack
.append( self
._outstream 
) 
 223             self
._outstream 
= value
 
 224         elif value 
is None and len(self
._outstream
_stack
) > 0: 
 225             self
._outstream 
= self
._outstream
_stack
.pop(-1) 
 228 #------------------------------------------------------------ 
 230 if __name__ 
== "__main__": 
 234     wx
.Log_SetActiveTarget( wx
.LogStderr() ) 
 235     logger 
= Logger('module') 
 238     logger('test __call__ interface') 
 239     dbg('testing wxLog output to stderr:', wxlog
=1, indent
=1) 
 241     dbg('testing wx.LogNull:') 
 242     devnull 
= wx
.LogNull() 
 243     dbg('4,5,6...') # shouldn't print, according to doc... 
 245     dbg('(resuming to wx.LogStdErr)', '7,8,9...', indent
=0) 
 246     dbg('disabling wx.Log output, switching to stderr:') 
 247     dbg(wxlog
=0, stream
=sys
.stderr
) 
 248     dbg(logger
._outstream
, 'switching back to stdout:') 
 250     dbg(logger
._outstream 
) 
 252         dbg('foo:', indent
=1) 
 254     foo('testing dbg inside function') 
 256         def __init__(self
, name
): 
 257             Logger
.__init
__(self
, name
) 
 258         def enable(self
, value
): 
 259             self
.dbg(enable
=value
) 
 261             self
.dbg('foo:', indent
=1) 
 262             self
.dbg(str, indent
=0) 
 263     f 
= bar('class mixin') 
 264     f
.foo("shouldn't print") 
 266     f
.foo("should print") 
 267     dbg('test completed.', enable
=0) 
 268     dbg('(double-checking ;-)')