]>
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) 
 151             strs 
= [str(arg
) for arg 
in args
] 
 152             output 
= ' '.join(strs
) 
 153             if self
.name
: output 
= self
.name
+': ' + output
 
 154             output 
= ' ' * 3 * self
._indent 
+ output
 
 157                 from wxPython
.wx 
import wxLogMessage    
# (if not already imported) 
 160                 self
._outstream
.write(output 
+ '\n') 
 161                 self
._outstream
.flush() 
 165         for kwarg
, value 
in kwargs
.items(): 
 166             if kwarg 
== 'indent': 
 167                 self
.SetIndent(value
) 
 168             elif kwarg 
== 'enable': 
 169                 self
.SetEnabled(value
) 
 170             elif kwarg 
== 'suspend': 
 171                 self
.SetSuspend(value
) 
 172             elif kwarg 
== 'wxlog': 
 174             elif kwarg 
== 'stream': 
 175                 self
.SetStream(value
) 
 177     # aliases for the log function 
 178     dbg 
= log       
# backwards compatible 
 180     __call__ 
= log  
# this one lets you 'call' the instance directly 
 183     def SetEnabled(self
, value
): 
 188                 self
.dbg('dbg enabled') 
 191                 self
.dbg('dbg disabled') 
 195     def SetSuspend(self
, value
): 
 198         elif self
._suspend 
> 0: 
 202     def SetIndent(self
, value
): 
 205         elif self
._indent 
> 0: 
 209     def SetWxLog(self
, value
): 
 213     def SetStream(self
, value
): 
 215             self
._outstream
_stack
.append( self
._outstream 
) 
 216             self
._outstream 
= value
 
 217         elif value 
is None and len(self
._outstream
_stack
) > 0: 
 218             self
._outstream 
= self
._outstream
_stack
.pop(-1) 
 221 #------------------------------------------------------------ 
 223 if __name__ 
== "__main__": 
 227     wx
.Log_SetActiveTarget( wx
.LogStderr() ) 
 228     logger 
= Logger('module') 
 231     logger('test __call__ interface') 
 232     dbg('testing wxLog output to stderr:', wxlog
=1, indent
=1) 
 234     dbg('testing wx.LogNull:') 
 235     devnull 
= wx
.LogNull() 
 236     dbg('4,5,6...') # shouldn't print, according to doc... 
 238     dbg('(resuming to wx.LogStdErr)', '7,8,9...', indent
=0) 
 239     dbg('disabling wx.Log output, switching to stderr:') 
 240     dbg(wxlog
=0, stream
=sys
.stderr
) 
 241     dbg(logger
._outstream
, 'switching back to stdout:') 
 243     dbg(logger
._outstream 
) 
 245         dbg('foo:', indent
=1) 
 247     foo('testing dbg inside function') 
 249         def __init__(self
, name
): 
 250             Logger
.__init
__(self
, name
) 
 251         def enable(self
, value
): 
 252             self
.dbg(enable
=value
) 
 254             self
.dbg('foo:', indent
=1) 
 255             self
.dbg(str, indent
=0) 
 256     f 
= bar('class mixin') 
 257     f
.foo("shouldn't print") 
 259     f
.foo("should print") 
 260     dbg('test completed.', enable
=0) 
 261     dbg('(double-checking ;-)')