]>
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 ;-)')