diff --git a/direct/src/showbase/PythonUtil.py b/direct/src/showbase/PythonUtil.py index 0dd81838df..d4ffd6213b 100644 --- a/direct/src/showbase/PythonUtil.py +++ b/direct/src/showbase/PythonUtil.py @@ -33,8 +33,7 @@ __all__ = ['enumerate', 'unique', 'indent', 'nonRepeatingRandomList', 'pandaBreak','pandaTrace','formatTimeCompact','DestructiveScratchPad', 'deeptype','getProfileResultString','StdoutCapture','StdoutPassthrough', 'Averager', 'getRepository', 'formatTimeExact', 'startSuperLog', 'endSuperLog', -'typeName', 'safeTypeName', 'histogramDict', 'unescapeHtmlString', -'bp', 'bpGroup', 'bpDecorator', ] +'typeName', 'safeTypeName', 'histogramDict', 'unescapeHtmlString', 'bpdb', ] import types import string @@ -4310,8 +4309,12 @@ if __debug__: assert repeatableRepr({1: 'a', 2: 'b'}) == repeatableRepr({2: 'b', 1: 'a'}) assert repeatableRepr(set([1,2,3])) == repeatableRepr(set([3,2,1])) -#breakpoint system - kanpatel -class bpDebugger: +#bpdb - breakpoint debugging system +#kanpatel +bpEnabled = True +class BpDb: + lastBp = None + def set_trace(self, frameCount=1): #find usefule frame self.currFrame = sys._getframe() @@ -4322,46 +4325,155 @@ class bpDebugger: #set up and start debuggger self.pdb = pdb.Pdb() - self.pdb.do_alias('aa breakpoint.debugger.addAliases()') + self.pdb.do_alias('aa bpdb.addAliases()') self.addAliases() self.pdb.set_trace(interactFrame); def addAliases(self): self.aliases = {} - #bpDebugger cmds - self.makeAlias('_i', 'breakpoint.lastBp.ignore(%*)') - self.makeAlias('_t', 'breakpoint.lastBp.toggle(%*)') - self.makeAlias('_tg', 'breakpoint.lastBp.toggleGroup(%*)') - self.makeAlias('_z', 'breakpoint.lastBp.reset(%*)') - self.makeAlias('_h', 'breakpoint.bpdb.displayHelp()') - self.makeAlias('_ua', 'breakpoint.bpdb.removeAliases()') + #bpdb cmds + self.makeAlias('_i', 'bpdb.lastBp.ignore(%*)') + self.makeAlias('_t', 'bpdb.lastBp.toggle(%*)') + self.makeAlias('_tg', 'bpdb.lastBp.toggleGroup(%*)') + self.makeAlias('_z', 'bpdb.lastBp.reset(%*)') + self.makeAlias('_h', 'bpdb.displayHelp()') + self.makeAlias('_ua', 'bpdb.removeAliases()') def makeAlias(self, name, cmd): self.aliases[name] = cmd self.pdb.do_alias('%s %s'%(name,cmd)) - + def removeAliases(self): for name in self.aliases.iterkeys(): self.pdb.do_unalias(name) self.aliases = {} - print '(bpDebugger aliases removed)' + print '(bpdb aliases removed)' def displayHelp(self): print 'You may use normal pdb commands plus the following:' - print ' _i n set ignore count for this breakpoint to n' - print ' _t toggle this breakpoint' - print ' _tg toggle this breakpoint group' - print ' _z clear all settings for this breakpoint (name)' - print ' _h displays this usage help' - print ' _ua unalias these commands from pdb' + #print ' cmd [param ] [cmd] does )this( with [param] (default is def)' + #print ' -----------------------------------------------------------------------' + print ' _i [n <0>, name=] set ignore count for breakpoint [name] to [n]' + print ' _t [name ] toggle breakpoint name [name]' + print ' _tg [grp ] toggle breakpoint group [grp]' + print ' _z [name ] clear all settings for breakpoint [name]' + print ' _h displays this usage help' + print ' _ua unalias these commands from pdb' + @staticmethod + def bp(name=None, grp=None, cfg=None, iff=True, frameCount=1): + bpi = bp(name=name, grp=grp, cfg=cfg, iff=iff) + bpi.maybeBreak(frameCount=frameCount+1) + + @staticmethod + def bpCall(name=None,grp=None,cfg=None,iff=True,frameCount=1,onEnter=1,onExit=0): + def decorator(f): + return f + + try: + if not (__dev__ or ConfigVariableBool('force-breakpoint', 0).getValue()): + return decorator + + #default cfg to module name + #TBD: should 1 be used instead of frameCount below? + decoratingModule = inspect.getmodule(inspect.stack()[frameCount][0]) + #inspect.stack()[-2][0].f_globals + moduleName = decoratingModule.__name__ + if cfg is None and moduleName != '__main__': + #get only leaf module name + moduleName = moduleName.split()[-1] + #prune 'Distributed' and 'AI/UD/OV' + if moduleName.find("Distributed") != -1: + moduleName = moduleName[len("Distributed"):] + moduleLen = len(moduleName) + if moduleLen > 2: + for suffix in ['AI','UD','OV']: + suffixPos = moduleName.rfind(suffix) + if suffixPos == moduleLen - 2: + moduleName = moduleName[:moduleLen-2] + break + cfg = moduleName + + # determine whether we should use the decorator + # based on the value of dConfigParam. + if cfg: + dConfigParamList = [] + dConfigParams = choice(isinstance(cfg, (list,tuple)), cfg, (cfg,)) + dConfigParamList = [param for param in dConfigParams \ + if ConfigVariableBool('want-breakpoint-%s' % (param,), 0).getValue()] + + if not dConfigParamList: + return decorator + + #default grp to context name + if grp is None: + for i in range(frameCount, len(inspect.stack())):#frameCount or 0? + decoratingContexts = inspect.stack()[i][4] + if not decoratingContexts: + continue + contextTokens = decoratingContexts[0].split() + if contextTokens[0] in ['class','def'] and len(contextTokens) > 1: + decoratingContexts[0] = decoratingContexts[0].replace('(',' ').replace(':',' ') + contextTokens = decoratingContexts[0].split() + className = contextTokens[1] + grp = className + break + + except NameError,e: + assert not "Error generating breakpoint decoration for function or method." + return decorator + + def decorator(f): + 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 -bpEnabled = True class bp: - bpdb = bpDebugger() grpInfos = {} nameInfos = {} - lastBp = None def __init__(self, name=None, grp=None, cfg=None, iff=True): #check early out conditions @@ -4377,7 +4489,7 @@ class bp: self.iff = iff #cache this as the latest bp - bp.lastBp = self + bpdb.lastBp = self @staticmethod def prettyName(name=None, grp=None, cfg=None, q=0): @@ -4389,8 +4501,8 @@ class bp: prettyName += choice(q, "'", '') return prettyName - def displayContextHint(self): - contextString = self.prettyName(name=self.name,grp=self.grp,cfg=self.cfg) + def displayContextHint(self, displayPrefix=''): + contextString = displayPrefix + self.prettyName(name=self.name,grp=self.grp,cfg=self.cfg) dashes = '-'*max(0, (80 - len(contextString) - 4) / 2) print '<%s %s %s>'%(dashes,contextString,dashes) @@ -4424,9 +4536,9 @@ class bp: self.nameInfos[name] = {} print '%s has been reset.'%(self.prettyName(name,q=1),) - def maybeBreak(self, iff=True, frameCount=1): + def maybeBreak(self, iff=True, frameCount=1,displayPrefix=''): if self.shouldBreak(iff): - self.doBreak(frameCount=frameCount+1) + self.doBreak(frameCount=frameCount+1,displayPrefix=displayPrefix) def shouldBreak(self,iff=True): #check easy early out @@ -4456,128 +4568,17 @@ class bp: #all conditions go return True - def doBreak(self, frameCount=1): + def doBreak(self, frameCount=1,displayPrefix=''): #accumulate hit count if 'lifetime' in bp.nameInfos[self.name]: bp.nameInfos[self.name]['lifetime'] -= 1 bp.nameInfos[self.name]['count'] = bp.nameInfos[self.name].get('count', 0) + 1 #setup debugger - self.displayContextHint() - self.bpdb.set_trace(frameCount=frameCount+1) - - -class bpStub: - def __init__(self,name,grp=None,cfg=None,iff=True): - pass - def prettyName(self, name=None, grp=None, cfg=None, q=0): - return '(bp Disabled)' - def displayContextHint(self): - pass - def enable(self, enabled=True, name=None): - pass - def toggle(self, name=None): - pass - def toggleGroup(self, grp=None): - pass - def ignore(self, ignoreCount=0, name=None): - pass - def reset(self, name=None): - pass - def maybeBreak(self, iff=True, frameCount=1): - pass - def shouldBreak(self,iff=True): - return False - def doBreak(self, frameCount=1): - pass - -if not bpEnabled: - bp = bpStub - -def bpDecorator(name=None,grp=None,cfg=None,iff=True,frameCount=1): - def decorator(f): - return f - - try: - if not (__dev__ or ConfigVariableBool('force-breakpoint', 0).getValue()): - return decorator - - #default cfg to module name - #TBD: should 1 be used instead of frameCount below? - decoratingModule = inspect.getmodule(inspect.stack()[frameCount][0]) - #inspect.stack()[-2][0].f_globals - moduleName = decoratingModule.__name__ - if cfg is None and moduleName != '__main__': - #get only leaf module name - moduleName = moduleName.split()[-1] - #prune 'Distributed' and 'AI/UD/OV' - if moduleName.find("Distributed") != -1: - moduleName = moduleName[len("Distributed"):] - moduleLen = len(moduleName) - if moduleLen > 2: - for suffix in ['AI','UD','OV']: - suffixPos = moduleName.rfind(suffix) - if suffixPos == moduleLen - 2: - moduleName = moduleName[:moduleLen-2] - break - cfg = moduleName - - # determine whether we should use the decorator - # based on the value of dConfigParam. - if cfg: - dConfigParamList = [] - dConfigParams = choice(isinstance(cfg, (list,tuple)), cfg, (cfg,)) - dConfigParamList = [param for param in dConfigParams \ - if ConfigVariableBool('want-breakpoint-%s' % (param,), 0).getValue()] - - if not dConfigParamList: - return decorator - - #default grp to context name - if grp is None: - for i in range(frameCount, len(inspect.stack())):#frameCount or 0? - decoratingContexts = inspect.stack()[i][4] - if not decoratingContexts: - continue - contextTokens = decoratingContexts[0].split() - if contextTokens[0] in ['class','def'] and len(contextTokens) > 1: - decoratingContexts[0] = decoratingContexts[0].replace('(',' ').replace(':',' ') - contextTokens = decoratingContexts[0].split() - className = contextTokens[1] - grp = className - break - - except NameError,e: - assert not "Error generating breakpoint decoration for function or method." - return decorator - - def decorator(f): - 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) - dbp.maybeBreak(iff=iff,frameCount=frameCount+1) - f_result = f(*args, **kwds) - 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 - -def bpGroup(*args, **kArgs): - argsCopy = args[:] - def functor(*cArgs, **ckArgs): - kArgs.update(ckArgs) - return bp(*(cArgs), **kArgs).maybeBreak(frameCount=kArgs.get('frameCount',1)+1) - return functor - + self.displayContextHint(displayPrefix=displayPrefix) + bpdb.set_trace(frameCount=frameCount+1) +bpdb = BpDb() import __builtin__ __builtin__.Functor = Functor @@ -4639,6 +4640,4 @@ __builtin__.typeName = typeName __builtin__.safeTypeName = safeTypeName __builtin__.histogramDict = histogramDict __builtin__.repeatableRepr = repeatableRepr -__builtin__.breakpoint = choice(bpEnabled, bp, bpStub) -__builtin__.breakpointGroup = bpGroup -__builtin__.breakpointDecorator = bpDecorator +__builtin__.bpdb = bpdb