1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15  _version_ = '1.4.0' 
 16   
 17  """\ 
 18   
 19  Generic debug class 
 20   
 21  Other modules can always define extra debug flags for local usage, as long as 
 22  they make sure they append them to debug_flags 
 23   
 24  Also its always a good thing to prefix local flags with something, to reduce risk 
 25  of coliding flags. Nothing breaks if two flags would be identical, but it might  
 26  activate unintended debugging. 
 27   
 28  flags can be numeric, but that makes analysing harder, on creation its 
 29  not obvious what is activated, and when flag_show is given, output isnt 
 30  really meaningfull. 
 31   
 32  This Debug class can either be initialized and used on app level, or used independantly 
 33  by the individual classes. 
 34   
 35  For samples of usage, see samples subdir in distro source, and selftest 
 36  in this code 
 37       
 38  """ 
 39   
 40   
 41   
 42  import sys 
 43  import traceback 
 44  import time 
 45  import os 
 46   
 47  import types 
 48   
 49  if os.environ.has_key('TERM'): 
 50      colors_enabled=True 
 51  else: 
 52      colors_enabled=False 
 53   
 54  color_none         = chr(27) + "[0m" 
 55  color_black        = chr(27) + "[30m" 
 56  color_red          = chr(27) + "[31m" 
 57  color_green        = chr(27) + "[32m" 
 58  color_brown        = chr(27) + "[33m" 
 59  color_blue         = chr(27) + "[34m" 
 60  color_magenta      = chr(27) + "[35m" 
 61  color_cyan         = chr(27) + "[36m" 
 62  color_light_gray   = chr(27) + "[37m" 
 63  color_dark_gray    = chr(27) + "[30;1m" 
 64  color_bright_red   = chr(27) + "[31;1m" 
 65  color_bright_green = chr(27) + "[32;1m" 
 66  color_yellow       = chr(27) + "[33;1m" 
 67  color_bright_blue  = chr(27) + "[34;1m" 
 68  color_purple       = chr(27) + "[35;1m" 
 69  color_bright_cyan  = chr(27) + "[36;1m" 
 70  color_white        = chr(27) + "[37;1m" 
 71   
 72   
 73  """ 
 74  Define your flags in yor modules like this: 
 75   
 76  from debug import * 
 77   
 78  DBG_INIT = 'init'                ; debug_flags.append( DBG_INIT ) 
 79  DBG_CONNECTION = 'connection'    ; debug_flags.append( DBG_CONNECTION ) 
 80   
 81   The reason for having a double statement wis so we can validate params 
 82   and catch all undefined debug flags 
 83    
 84   This gives us control over all used flags, and makes it easier to allow 
 85   global debugging in your code, just do something like 
 86    
 87   foo = Debug( debug_flags ) 
 88    
 89   group flags, that is a flag in it self containing multiple flags should be 
 90   defined without the debug_flags.append() sequence, since the parts are already 
 91   in the list, also they must of course be defined after the flags they depend on ;) 
 92   example: 
 93   
 94  DBG_MULTI = [ DBG_INIT, DBG_CONNECTION ] 
 95   
 96   
 97   
 98    NoDebug 
 99    ------- 
100    To speed code up, typically for product releases or such 
101    use this class instead if you globaly want to disable debugging 
102  """ 
103   
104   
107          self.debug_flags = [] 
 108 -    def show( self,  *args, **kwargs): 
 110 -    def Show( self,  *args, **kwargs): 
 114      colors={} 
 117       
118   
119  LINE_FEED = '\n' 
120   
121   
123 -    def __init__( self, 
124                     
125                     
126                     
127                    active_flags = None, 
128                     
129                     
130                     
131                    log_file = sys.stderr, 
132                     
133                     
134                     
135                     
136                     
137                     
138                    prefix = 'DEBUG: ', 
139                    sufix = '\n', 
140                     
141                     
142                     
143                     
144                     
145                     
146                    time_stamp = 0, 
147                     
148                     
149                     
150                     
151                     
152                     
153                     
154                     
155                    flag_show = None, 
156                     
157                     
158                     
159                     
160                    validate_flags = 1, 
161                     
162                     
163                     
164                    welcome = -1 
165                    ): 
 166           
167          self.debug_flags = [] 
168          if welcome == -1: 
169              if active_flags and len(active_flags): 
170                  welcome = 1 
171              else: 
172                  welcome = 0 
173               
174          self._remove_dupe_flags() 
175          if log_file: 
176              if type( log_file ) is type(''): 
177                  try: 
178                      self._fh = open(log_file,'w') 
179                  except: 
180                      print 'ERROR: can open %s for writing' 
181                      sys.exit(0) 
182              else:  
183                  self._fh = log_file 
184          else: 
185              self._fh = sys.stdout 
186            
187          if time_stamp not in (0,1,2): 
188              msg2 = '%s' % time_stamp 
189              raise 'Invalid time_stamp param', msg2 
190          self.prefix = prefix 
191          self.sufix = sufix 
192          self.time_stamp = time_stamp 
193          self.flag_show = None  
194          self.validate_flags = validate_flags 
195   
196          self.active_set( active_flags ) 
197          if welcome: 
198              self.show('') 
199              caller = sys._getframe(1)  
200              try: 
201                  mod_name= ":%s" % caller.f_locals['__name__'] 
202              except: 
203                  mod_name = "" 
204              self.show('Debug created for %s%s' % (caller.f_code.co_filename, 
205                                                     mod_name )) 
206              self.show(' flags defined: %s' % ','.join( self.active )) 
207               
208          if type(flag_show) in (type(''), type(None)): 
209              self.flag_show = flag_show 
210          else: 
211              msg2 = '%s' % type(flag_show ) 
212              raise 'Invalid type for flag_show!', msg2 
 213   
214   
215           
216   
217   
218 -    def show( self, msg, flag = None, prefix = None, sufix = None, 
219                lf = 0 ): 
 220          """ 
221          flag can be of folowing types: 
222              None - this msg will always be shown if any debugging is on 
223              flag - will be shown if flag is active 
224              (flag1,flag2,,,) - will be shown if any of the given flags  
225                                 are active 
226   
227          if prefix / sufix are not given, default ones from init will be used 
228           
229          lf = -1 means strip linefeed if pressent 
230          lf = 1 means add linefeed if not pressent 
231          """ 
232           
233          if self.validate_flags: 
234              self._validate_flag( flag ) 
235               
236          if not self.is_active(flag): 
237              return 
238          if prefix: 
239              pre = prefix 
240          else: 
241              pre = self.prefix 
242          if sufix: 
243              suf = sufix 
244          else: 
245              suf = self.sufix 
246   
247          if self.time_stamp == 2: 
248              output = '%s%s ' % ( pre, 
249                                   time.strftime('%b %d %H:%M:%S', 
250                                   time.localtime(time.time() )), 
251                                   ) 
252          elif self.time_stamp == 1: 
253              output = '%s %s' % ( time.strftime('%b %d %H:%M:%S', 
254                                   time.localtime(time.time() )), 
255                                   pre, 
256                                   ) 
257          else: 
258              output = pre 
259               
260          if self.flag_show: 
261              if flag: 
262                  output = '%s%s%s' % ( output, flag, self.flag_show ) 
263              else: 
264                   
265                   
266                  output = '%s %s' % ( output, self.flag_show ) 
267   
268          output = '%s%s%s' % ( output, msg, suf ) 
269          if lf: 
270               
271              last_char = output[-1] 
272              if lf == 1 and last_char != LINE_FEED: 
273                  output = output + LINE_FEED 
274              elif lf == -1 and last_char == LINE_FEED: 
275                  output = output[:-1] 
276          try: 
277              self._fh.write( output ) 
278          except: 
279               
280              s=u'' 
281              for i in range(len(output)): 
282                  if ord(output[i]) < 128: 
283                      c = output[i] 
284                  else: 
285                      c = '?' 
286                  s=s+c 
287              self._fh.write( '%s%s%s' % ( pre, s, suf )) 
288          self._fh.flush() 
 289               
290                   
292          'If given flag(s) should generate output.' 
293   
294           
295          if not self.active: 
296              return 0 
297          if not flag or flag in self.active: 
298              return 1 
299          else: 
300               
301              if type( flag ) in ( type(()), type([]) ): 
302                  for s in flag: 
303                      if s in self.active: 
304                          return 1 
305          return 0 
 306   
307       
309          "returns 1 if any flags where actually set, otherwise 0." 
310          r = 0 
311          ok_flags = [] 
312          if not active_flags: 
313               
314              self.active = [] 
315          elif type( active_flags ) in ( types.TupleType, types.ListType ): 
316              flags = self._as_one_list( active_flags ) 
317              for t in flags: 
318                  if t not in self.debug_flags: 
319                      sys.stderr.write('Invalid debugflag given: %s\n' % t ) 
320                  ok_flags.append( t ) 
321                   
322              self.active = ok_flags 
323              r = 1 
324          else: 
325               
326              try: 
327                  flags = active_flags.split(',') 
328              except: 
329                  self.show( '***' ) 
330                  self.show( '*** Invalid debug param given: %s' % active_flags ) 
331                  self.show( '*** please correct your param!' ) 
332                  self.show( '*** due to this, full debuging is enabled' ) 
333                  self.active = self.debug_flags 
334               
335              for f in flags: 
336                  s = f.strip() 
337                  ok_flags.append( s ) 
338              self.active = ok_flags 
339   
340          self._remove_dupe_flags() 
341          return r 
 342       
344          "returns currently active flags." 
345          return self.active 
 346       
347       
349          """ init param might contain nested lists, typically from group flags. 
350           
351          This code organises lst and remves dupes 
352          """ 
353          if type( items ) <> type( [] ) and type( items ) <> type( () ): 
354              return [ items ] 
355          r = [] 
356          for l in items: 
357              if type( l ) == type([]): 
358                  lst2 = self._as_one_list( l ) 
359                  for l2 in lst2:  
360                      self._append_unique_str(r, l2 ) 
361              elif l == None: 
362                  continue 
363              else: 
364                  self._append_unique_str(r, l ) 
365          return r 
 366       
367       
369          """filter out any dupes.""" 
370          if type(item) <> type(''): 
371              msg2 = '%s' % item 
372              raise 'Invalid item type (should be string)',msg2 
373          if item not in lst: 
374              lst.append( item ) 
375          return lst 
 376   
377       
379          'verify that flag is defined.' 
380          if flags: 
381              for f in self._as_one_list( flags ): 
382                  if not f in self.debug_flags: 
383                      msg2 = '%s' % f 
384                      raise 'Invalid debugflag given', msg2 
 385   
387          """ 
388          if multiple instances of Debug is used in same app,  
389          some flags might be created multiple time, filter out dupes 
390          """ 
391          unique_flags = [] 
392          for f in self.debug_flags: 
393              if f not in unique_flags: 
394                  unique_flags.append(f) 
395          self.debug_flags = unique_flags 
 396   
397      colors={} 
398 -    def Show(self, flag, msg, prefix=''): 
 399          msg=msg.replace('\r','\\r').replace('\n','\\n').replace('><','>\n  <') 
400          if not colors_enabled: pass 
401          elif self.colors.has_key(prefix): msg=self.colors[prefix]+msg+color_none 
402          else: msg=color_none+msg 
403          if not colors_enabled: prefixcolor='' 
404          elif self.colors.has_key(flag): prefixcolor=self.colors[flag] 
405          else: prefixcolor=color_none 
406           
407          if prefix=='error': 
408              _exception = sys.exc_info() 
409              if _exception[0]: 
410                  msg=msg+'\n'+''.join(traceback.format_exception(_exception[0], _exception[1], _exception[2])).rstrip() 
411           
412          prefix= self.prefix+prefixcolor+(flag+' '*12)[:12]+' '+(prefix+' '*6)[:6] 
413          self.show(msg, flag, prefix) 
 414   
416          if not self.active: return 0 
417          if not flag or flag in self.active and DBG_ALWAYS not in self.active or flag not in self.active and DBG_ALWAYS in self.active : return 1 
418          return 0 
 419   
420  DBG_ALWAYS='always' 
421   
422   
423   
424