]>
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: 
  79     from wxPython.tools.dbg import Logger 
  81     dbg('something to print') 
  83 Using this fairly simple mechanism, it is possible to get fairly 
  84 useful debugging output in a program.  Consider the following 
  87 >>> d = {1:'a', 2:'dictionary', 3:'of', 4:'words'} 
  88 >>> dbg = dbg.Logger('module') 
  92 ...     dbg('foo', indent=1) 
  94 ...     dbg('end of foo', indent=0) 
  97 ...     dbg('bar', indent=1) 
  98 ...     dbg('contents of d:', indent=1) 
 101 ...     for key, value in l: 
 102 ...         dbg('%d =' % key, value) 
 104 ...     dbg('end of bar', indent=0) 
 109       module: contents of d: 
 111          module: 2 = dictionary 
 122     def __init__(self
, name
=None): 
 125         self
._indent 
= 0     # current number of indentations 
 126         self
._dbg 
= 0        # enable/disable flag 
 127         self
._suspend 
= 0    # allows code to "suspend/resume" potential dbg output 
 128         self
._wxLog 
= 0      # use wxLogMessage for debug output 
 129         self
._outstream 
= sys
.stdout  
# default output stream 
 130         self
._outstream
_stack 
= []    # for restoration of streams as necessary 
 140     def log(self
, *args
, **kwargs
): 
 142         This function provides a useful framework for generating 
 143         optional debugging output that can be displayed at an 
 144         arbitrary level of indentation. 
 146         if not self
._dbg 
and not 'enable' in kwargs
.keys(): 
 149         if self
._dbg 
and len(args
) and not self
._suspend
: 
 150             # (emulate print functionality; handle unicode as best as possible:) 
 154                     strs
.append(str(arg
)) 
 156                     strs
.append(repr(arg
)) 
 158             output 
= ' '.join(strs
) 
 159             if self
.name
: output 
= self
.name
+': ' + output
 
 160             output 
= ' ' * 3 * self
._indent 
+ output
 
 163                 from wxPython
.wx 
import wxLogMessage    
# (if not already imported) 
 166                 self
._outstream
.write(output 
+ '\n') 
 167                 self
._outstream
.flush() 
 171         for kwarg
, value 
in kwargs
.items(): 
 172             if kwarg 
== 'indent': 
 173                 self
.SetIndent(value
) 
 174             elif kwarg 
== 'enable': 
 175                 self
.SetEnabled(value
) 
 176             elif kwarg 
== 'suspend': 
 177                 self
.SetSuspend(value
) 
 178             elif kwarg 
== 'wxlog': 
 180             elif kwarg 
== 'stream': 
 181                 self
.SetStream(value
) 
 183     # aliases for the log function 
 184     dbg 
= log       
# backwards compatible 
 186     __call__ 
= log  
# this one lets you 'call' the instance directly 
 189     def SetEnabled(self
, value
): 
 194                 self
.dbg('dbg enabled') 
 197                 self
.dbg('dbg disabled') 
 201     def SetSuspend(self
, value
): 
 204         elif self
._suspend 
> 0: 
 208     def SetIndent(self
, value
): 
 211         elif self
._indent 
> 0: 
 215     def SetWxLog(self
, value
): 
 219     def SetStream(self
, value
): 
 221             self
._outstream
_stack
.append( self
._outstream 
) 
 222             self
._outstream 
= value
 
 223         elif value 
is None and len(self
._outstream
_stack
) > 0: 
 224             self
._outstream 
= self
._outstream
_stack
.pop(-1) 
 227 #------------------------------------------------------------ 
 229 if __name__ 
== "__main__": 
 233     wx
.Log_SetActiveTarget( wx
.LogStderr() ) 
 234     logger 
= Logger('module') 
 237     logger('test __call__ interface') 
 238     dbg('testing wxLog output to stderr:', wxlog
=1, indent
=1) 
 240     dbg('testing wx.LogNull:') 
 241     devnull 
= wx
.LogNull() 
 242     dbg('4,5,6...') # shouldn't print, according to doc... 
 244     dbg('(resuming to wx.LogStdErr)', '7,8,9...', indent
=0) 
 245     dbg('disabling wx.Log output, switching to stderr:') 
 246     dbg(wxlog
=0, stream
=sys
.stderr
) 
 247     dbg(logger
._outstream
, 'switching back to stdout:') 
 249     dbg(logger
._outstream 
) 
 251         dbg('foo:', indent
=1) 
 253     foo('testing dbg inside function') 
 255         def __init__(self
, name
): 
 256             Logger
.__init
__(self
, name
) 
 257         def enable(self
, value
): 
 258             self
.dbg(enable
=value
) 
 260             self
.dbg('foo:', indent
=1) 
 261             self
.dbg(str, indent
=0) 
 262     f 
= bar('class mixin') 
 263     f
.foo("shouldn't print") 
 265     f
.foo("should print") 
 266     dbg('test completed.', enable
=0) 
 267     dbg('(double-checking ;-)')