bpdb - breakpoints default to cfg=module, grp=class, name=line number

This commit is contained in:
Ken Patel 2010-04-20 02:36:29 +00:00
parent 905f339346
commit 8697b40ccf

View File

@ -4309,10 +4309,9 @@ if __debug__:
assert repeatableRepr({1: 'a', 2: 'b'}) == repeatableRepr({2: 'b', 1: 'a'}) assert repeatableRepr({1: 'a', 2: 'b'}) == repeatableRepr({2: 'b', 1: 'a'})
assert repeatableRepr(set([1,2,3])) == repeatableRepr(set([3,2,1])) assert repeatableRepr(set([1,2,3])) == repeatableRepr(set([3,2,1]))
#bpdb - breakpoint debugging system #bpdb - breakpoint debugging system (kanpatel - 04/2010)
#kanpatel
bpEnabled = True
class BpDb: class BpDb:
enabled = True
lastBp = None lastBp = None
def set_trace(self, frameCount=1): def set_trace(self, frameCount=1):
@ -4360,9 +4359,21 @@ class BpDb:
print ' _h displays this usage help' print ' _h displays this usage help'
print ' _ua unalias these commands from pdb' print ' _ua unalias these commands from pdb'
@staticmethod
def verifyEnabled():
try:
bpdb.enabled = __dev__
bpdb.enabled = config.GetBool('force-breakpoints', bpdb.enabled)
except:
pass
return bpdb.enabled
@staticmethod @staticmethod
def bp(name=None, grp=None, cfg=None, iff=True, frameCount=1): def bp(name=None, grp=None, cfg=None, iff=True, frameCount=1):
bpi = bp(name=name, grp=grp, cfg=cfg, iff=iff) if not bpdb.enabled or not bpdb.verifyEnabled():
return
bpi = bp(name=name, grp=grp, cfg=cfg, iff=iff,frameCount=frameCount+1)
bpi.maybeBreak(frameCount=frameCount+1) bpi.maybeBreak(frameCount=frameCount+1)
@staticmethod @staticmethod
@ -4370,15 +4381,61 @@ class BpDb:
def decorator(f): def decorator(f):
return f return f
try: if not bpdb.enabled or not bpdb.verifyEnabled():
if not (__dev__ or ConfigVariableBool('force-breakpoint', 0).getValue()):
return decorator return decorator
bpi = bp(name=name, grp=grp, cfg=cfg, iff=iff, frameCount=frameCount+1)
if bpi.disabled:
return decorator
def decorator(f):
def wrap(*args, **kwds):
#create our bp object
bpi.name = name or f.__name__
if onEnter:
bpi.maybeBreak(iff=iff,frameCount=frameCount+1,displayPrefix='Calling ')
f_result = f(*args, **kwds)
if onExit:
bpi.maybeBreak(iff=iff,frameCount=frameCount+1,displayPrefix='Exited ')
return f_result
wrap.func_name = f.func_name
wrap.func_dict = f.func_dict
wrap.func_doc = f.func_doc
wrap.__module__ = f.__module__
return wrap
return decorator
@staticmethod
def group(*args, **kArgs):
if not bpdb.enabled or not bpdb.verifyEnabled():
def functor(*cArgs, **ckArgs):
return
return functor
argsCopy = args[:]
def functor(*cArgs, **ckArgs):
ckArgs.update(kArgs)
ckArgs['frameCount'] = ckArgs.get('frameCount',1)+1
return bpdb.bp(*(cArgs), **ckArgs)
return functor
class bp:
grpInfos = {}
nameInfos = {}
def __init__(self, name=None, grp=None, cfg=None, iff=True, frameCount=1):
#check early out conditions
self.disabled = False
if not bpdb.enabled:
self.disabled = True
return
#default cfg to module name #default cfg to module name
#TBD: should 1 be used instead of frameCount below? callingModule = inspect.getmodule(inspect.stack()[frameCount][0])
decoratingModule = inspect.getmodule(inspect.stack()[frameCount][0]) moduleName = callingModule.__name__
#inspect.stack()[-2][0].f_globals
moduleName = decoratingModule.__name__
if cfg is None and moduleName != '__main__': if cfg is None and moduleName != '__main__':
#get only leaf module name #get only leaf module name
moduleName = moduleName.split()[-1] moduleName = moduleName.split()[-1]
@ -4394,97 +4451,48 @@ class BpDb:
break break
cfg = moduleName cfg = moduleName
# determine whether we should use the decorator # determine whether we should this bp is active
# based on the value of dConfigParam. # based on the value of cfg.
if cfg: if cfg:
dConfigParamList = [] dConfigParamList = []
dConfigParams = choice(isinstance(cfg, (list,tuple)), cfg, (cfg,)) dConfigParams = choice(isinstance(cfg, (list,tuple)), cfg, (cfg,))
dConfigParamList = [param for param in dConfigParams \ dConfigParamList = [param for param in dConfigParams \
if ConfigVariableBool('want-breakpoint-%s' % (param,), 0).getValue()] if ConfigVariableBool('want-breakpoint-%s' % (param,), 0).getValue()]
if not dConfigParamList: if not dConfigParamList:
return decorator self.disabled = True
return
#default grp to context name #default grp to context name
if grp is None: if grp is None:
for i in range(frameCount, len(inspect.stack())):#frameCount or 0? #look for class
decoratingContexts = inspect.stack()[i][4] for i in range(frameCount, len(inspect.stack())):
if not decoratingContexts: callingContexts = inspect.stack()[i][4]
if not callingContexts:
continue continue
contextTokens = decoratingContexts[0].split() #print i, callingContexts
contextTokens = callingContexts[0].split()
if contextTokens[0] in ['class','def'] and len(contextTokens) > 1: if contextTokens[0] in ['class','def'] and len(contextTokens) > 1:
decoratingContexts[0] = decoratingContexts[0].replace('(',' ').replace(':',' ') callingContexts[0] = callingContexts[0].replace('(',' ').replace(':',' ')
contextTokens = decoratingContexts[0].split() contextTokens = callingContexts[0].split()
className = contextTokens[1] className = contextTokens[1]
grp = className grp = className
break break
#look for self
if grp is None:
slf = inspect.stack()[frameCount][0].f_locals.get('self')
if slf:
className = slf.__class__.__name__
grp = className
except NameError,e: #default name to line number
assert not "Error generating breakpoint decoration for function or method." if name is None:
return decorator if frameCount < len(inspect.stack()):
lineno = inspect.stack()[frameCount][2]
def decorator(f): name = lineno
def wrap(*args, **kwds):
#create our bp object
dname = name or f.__name__
dgrp = grp
dcfg = cfg
dbp = bp(name=dname,grp=dgrp,cfg=dcfg)
if onEnter:
dbp.maybeBreak(iff=iff,frameCount=frameCount+1,displayPrefix='Entering ')
f_result = f(*args, **kwds)
if onExit:
dbp.maybeBreak(iff=iff,frameCount=frameCount+1,displayPrefix='Exited ')
return f_result
wrap.func_name = f.func_name
wrap.func_dict = f.func_dict
wrap.func_doc = f.func_doc
wrap.__module__ = f.__module__
return wrap
return decorator
@staticmethod
def group(*args, **kArgs):
argsCopy = args[:]
def functor(*cArgs, **ckArgs):
ckArgs.update(kArgs)
ckArgs['frameCount'] = ckArgs.get('frameCount',1)+1
return bpdb.bp(*(cArgs), **ckArgs)
return functor
if not bpEnabled:
@staticmethod
def brk(*args, **kArgs):
return
@staticmethod
def brkDec(*args, **kArgs):
def decorator(f):
return f
return decorator
@staticmethod
def group(*args, **kArgs):
def functor(*cArgs, **ckArgs):
return
return functor
class bp:
grpInfos = {}
nameInfos = {}
def __init__(self, name=None, grp=None, cfg=None, iff=True):
#check early out conditions
if not bpEnabled:
return
#store this breakpoint's settings #store this breakpoint's settings
self.name = name self.name = name
bp.nameInfos.setdefault(name, {})
self.grp = grp self.grp = grp
bp.grpInfos.setdefault(grp, {})
self.cfg = cfg self.cfg = cfg
self.iff = iff self.iff = iff
@ -4495,9 +4503,19 @@ class bp:
def prettyName(name=None, grp=None, cfg=None, q=0): def prettyName(name=None, grp=None, cfg=None, q=0):
prettyName = '' prettyName = ''
prettyName += choice(q, "'", '') prettyName += choice(q, "'", '')
prettyName += choice(cfg, '%s::'%(cfg,), '') if cfg:
prettyName += choice(grp, '%s.'%(grp,), '') prettyName += '%s'%(cfg,)
prettyName += choice(name, '%s'%(name,), '') if grp or name:
prettyName += '::'
if grp:
prettyName += '%s'%(grp,)
if name:
if isinstance(name, int):
prettyName += '(%s)'%(name,)
elif grp:
prettyName += '.%s'%(name,)
else:
prettyName += '%s'%(name,)
prettyName += choice(q, "'", '') prettyName += choice(q, "'", '')
return prettyName return prettyName
@ -4523,7 +4541,7 @@ class bp:
self.grpInfos.setdefault(grp, {}) self.grpInfos.setdefault(grp, {})
newEnabled = not self.grpInfos[grp].get('enabled', True) newEnabled = not self.grpInfos[grp].get('enabled', True)
self.grpInfos[grp]['enabled'] = newEnabled self.grpInfos[grp]['enabled'] = newEnabled
print '%s is now %s.'%(self.prettyName(grp,q=1),choice(newEnabled,'enabled','disabled'),) print 'group %s is now %s.'%(self.prettyName(grp,q=1),choice(newEnabled,'enabled','disabled'),)
def ignore(self, ignoreCount=0, name=None): def ignore(self, ignoreCount=0, name=None):
name = name or self.name name = name or self.name
@ -4542,9 +4560,15 @@ class bp:
def shouldBreak(self,iff=True): def shouldBreak(self,iff=True):
#check easy early out #check easy early out
if self.disabled:
return False
if not self.iff or not iff: if not self.iff or not iff:
return False return False
#make sure we exist
bp.grpInfos.setdefault(self.grp, {})
bp.nameInfos.setdefault(self.name, {})
#check disabled conditions #check disabled conditions
if not bp.grpInfos[self.grp].get('enabled', True): if not bp.grpInfos[self.grp].get('enabled', True):
return False return False
@ -4569,6 +4593,10 @@ class bp:
return True return True
def doBreak(self, frameCount=1,displayPrefix=''): def doBreak(self, frameCount=1,displayPrefix=''):
#make sure we exist
bp.grpInfos.setdefault(self.grp, {})
bp.nameInfos.setdefault(self.name, {})
#accumulate hit count #accumulate hit count
if 'lifetime' in bp.nameInfos[self.name]: if 'lifetime' in bp.nameInfos[self.name]:
bp.nameInfos[self.name]['lifetime'] -= 1 bp.nameInfos[self.name]['lifetime'] -= 1