mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
working exception variable dump
This commit is contained in:
parent
9c9d3d0707
commit
e79a864125
@ -1,8 +1,11 @@
|
|||||||
|
from pandac.PandaModules import ConfigConfigureGetConfigConfigShowbase as config
|
||||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||||
from direct.showbase.PythonUtil import fastRepr
|
from direct.showbase.PythonUtil import fastRepr
|
||||||
from exceptions import Exception
|
from exceptions import Exception
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import types
|
||||||
|
|
||||||
|
notify = directNotify.newCategory("ExceptionVarDump")
|
||||||
|
|
||||||
reentry = 0
|
reentry = 0
|
||||||
|
|
||||||
@ -11,30 +14,33 @@ def _varDump__init__(self, *args, **kArgs):
|
|||||||
if reentry > 0:
|
if reentry > 0:
|
||||||
return
|
return
|
||||||
reentry += 1
|
reentry += 1
|
||||||
|
# frame zero is this frame
|
||||||
f = 1
|
f = 1
|
||||||
self._savedExcString = None
|
self._savedExcString = None
|
||||||
self._savedStackFrames = []
|
self._savedStackFrames = []
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
frame = sys._getframe(f)
|
frame = sys._getframe(f)
|
||||||
|
except ValueError, e:
|
||||||
|
break
|
||||||
|
else:
|
||||||
f += 1
|
f += 1
|
||||||
self._savedStackFrames.append(frame)
|
self._savedStackFrames.append(frame)
|
||||||
except:
|
|
||||||
break
|
|
||||||
self._moved__init__(*args, **kArgs)
|
self._moved__init__(*args, **kArgs)
|
||||||
reentry -= 1
|
reentry -= 1
|
||||||
|
|
||||||
sReentry = 0
|
sReentry = 0
|
||||||
|
|
||||||
def _varDump__str__(self, *args, **kArgs):
|
def _varDump__print(exc):
|
||||||
global sReentry
|
global sReentry
|
||||||
|
global notify
|
||||||
if sReentry > 0:
|
if sReentry > 0:
|
||||||
return
|
return
|
||||||
sReentry += 1
|
sReentry += 1
|
||||||
if not self._savedExcString:
|
if not exc._savedExcString:
|
||||||
s = ''
|
s = ''
|
||||||
foundRun = False
|
foundRun = False
|
||||||
for frame in reversed(self._savedStackFrames):
|
for frame in reversed(exc._savedStackFrames):
|
||||||
filename = frame.f_code.co_filename
|
filename = frame.f_code.co_filename
|
||||||
codename = frame.f_code.co_name
|
codename = frame.f_code.co_name
|
||||||
if not foundRun and codename != 'run':
|
if not foundRun and codename != 'run':
|
||||||
@ -48,17 +54,59 @@ def _varDump__str__(self, *args, **kArgs):
|
|||||||
obj = locals[var]
|
obj = locals[var]
|
||||||
rep = fastRepr(obj)
|
rep = fastRepr(obj)
|
||||||
s += '::%s = %s\n' % (var, rep)
|
s += '::%s = %s\n' % (var, rep)
|
||||||
self._savedExcString = s
|
exc._savedExcString = s
|
||||||
self._savedStackFrames = None
|
exc._savedStackFrames = None
|
||||||
notify = directNotify.newCategory("ExceptionVarDump")
|
notify.info(exc._savedExcString)
|
||||||
notify.info(self._savedExcString)
|
|
||||||
str = self._moved__str__(*args, **kArgs)
|
|
||||||
sReentry -= 1
|
sReentry -= 1
|
||||||
return str
|
|
||||||
|
oldExcepthook = None
|
||||||
|
# store these values here so that Task.py can always reliably access these values
|
||||||
|
# from its main exception handler
|
||||||
|
wantVariableDump = False
|
||||||
|
dumpOnExceptionInit = False
|
||||||
|
|
||||||
|
def _excepthookDumpVars(eType, eValue, traceback):
|
||||||
|
s = 'DUMPING STACK FRAME VARIABLES'
|
||||||
|
tb = traceback
|
||||||
|
#import pdb;pdb.set_trace()
|
||||||
|
foundRun = False
|
||||||
|
while tb is not None:
|
||||||
|
frame = tb.tb_frame
|
||||||
|
code = frame.f_code
|
||||||
|
tb = tb.tb_next
|
||||||
|
# skip everything before the 'run' method, those frames have lots of
|
||||||
|
# not-useful information
|
||||||
|
if not foundRun:
|
||||||
|
if code.co_name == 'run':
|
||||||
|
foundRun = True
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
s += '\n File "%s", line %s, in %s' % (
|
||||||
|
code.co_filename, frame.f_lineno, code.co_name)
|
||||||
|
for name, val in frame.f_locals.iteritems():
|
||||||
|
r = fastRepr(val)
|
||||||
|
if type(r) is types.StringType:
|
||||||
|
r = r.replace('\n', '\\n')
|
||||||
|
s += '\n %s=%s' % (name, r)
|
||||||
|
s += '\n'
|
||||||
|
notify.info(s)
|
||||||
|
oldExcepthook(eType, eValue, traceback)
|
||||||
|
|
||||||
def install():
|
def install():
|
||||||
if not hasattr(Exception, '_moved__init__'):
|
global oldExcepthook
|
||||||
Exception._moved__init__ = Exception.__init__
|
global wantVariableDump
|
||||||
Exception.__init__ = _varDump__init__
|
global dumpOnExceptionInit
|
||||||
Exception._moved__str__ = Exception.__str__
|
|
||||||
Exception.__str__ = _varDump__str__
|
wantVariableDump = True
|
||||||
|
dumpOnExceptionInit = config.GetBool('variable-dump-on-exception-init', 0)
|
||||||
|
if dumpOnExceptionInit:
|
||||||
|
# this mode doesn't completely work because exception objects
|
||||||
|
# thrown by the interpreter don't get created until the
|
||||||
|
# stack has been unwound and an except block has been reached
|
||||||
|
if not hasattr(Exception, '_moved__init__'):
|
||||||
|
Exception._moved__init__ = Exception.__init__
|
||||||
|
Exception.__init__ = _varDump__init__
|
||||||
|
else:
|
||||||
|
if sys.excepthook is not _excepthookDumpVars:
|
||||||
|
oldExcepthook = sys.excepthook
|
||||||
|
sys.excepthook = _excepthookDumpVars
|
||||||
|
@ -2244,11 +2244,29 @@ def gcDebugOn():
|
|||||||
import gc
|
import gc
|
||||||
return (gc.get_debug() & gc.DEBUG_SAVEALL) == gc.DEBUG_SAVEALL
|
return (gc.get_debug() & gc.DEBUG_SAVEALL) == gc.DEBUG_SAVEALL
|
||||||
|
|
||||||
|
# base class for all Panda C++ objects
|
||||||
|
# libdtoolconfig doesn't seem to have this, grab it off of PandaNode
|
||||||
|
dtoolSuperBase = None
|
||||||
|
|
||||||
|
def _getDtoolSuperBase():
|
||||||
|
global dtoolSuperBase
|
||||||
|
from pandac.PandaModules import PandaNode
|
||||||
|
dtoolSuperBase = PandaNode('').__class__.__bases__[0].__bases__[0].__bases__[0]
|
||||||
|
|
||||||
def safeRepr(obj):
|
def safeRepr(obj):
|
||||||
|
global dtoolSuperBase
|
||||||
|
if dtoolSuperBase is None:
|
||||||
|
_getDtoolSuperBase()
|
||||||
|
|
||||||
|
if isinstance(obj, dtoolSuperBase):
|
||||||
|
# repr of C++ object could crash, particularly if the object has been deleted
|
||||||
|
return '<%s.%s instance at %s>' % (
|
||||||
|
obj.__class__.__module__, obj.__class__.__name__, hex(id(obj)))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return repr(obj)
|
return repr(obj)
|
||||||
except:
|
except:
|
||||||
return '<** FAILED REPR OF %s **>' % obj.__class__.__name__
|
return '<** FAILED REPR OF %s instance at %s **>' % (obj.__class__.__name__, hex(id(obj)))
|
||||||
|
|
||||||
def fastRepr(obj, maxLen=200, strFactor=10, _visitedIds=None):
|
def fastRepr(obj, maxLen=200, strFactor=10, _visitedIds=None):
|
||||||
""" caps the length of iterable types, so very large objects will print faster.
|
""" caps the length of iterable types, so very large objects will print faster.
|
||||||
@ -2302,7 +2320,10 @@ def fastRepr(obj, maxLen=200, strFactor=10, _visitedIds=None):
|
|||||||
else:
|
else:
|
||||||
return safeRepr(obj)
|
return safeRepr(obj)
|
||||||
else:
|
else:
|
||||||
return safeRepr(obj)
|
r = safeRepr(obj)
|
||||||
|
if len(r) > maxLen:
|
||||||
|
r = r[:maxLen]
|
||||||
|
return r
|
||||||
except:
|
except:
|
||||||
return '<** FAILED REPR OF %s **>' % obj.__class__.__name__
|
return '<** FAILED REPR OF %s **>' % obj.__class__.__name__
|
||||||
|
|
||||||
@ -2445,11 +2466,20 @@ class RefCounter:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def itype(obj):
|
def itype(obj):
|
||||||
|
# version of type that gives more complete information about instance types
|
||||||
|
global dtoolSuperBase
|
||||||
t = type(obj)
|
t = type(obj)
|
||||||
if t is types.InstanceType:
|
if t is types.InstanceType:
|
||||||
return '%s of <class %s>>' % (repr(types.InstanceType)[:-1],
|
return '%s of <class %s>>' % (repr(types.InstanceType)[:-1],
|
||||||
str(obj.__class__))
|
str(obj.__class__))
|
||||||
else:
|
else:
|
||||||
|
# C++ object instances appear to be types via type()
|
||||||
|
# check if this is a C++ object
|
||||||
|
if dtoolSuperBase is None:
|
||||||
|
_getDtoolSuperBase()
|
||||||
|
if isinstance(obj, dtoolSuperBase):
|
||||||
|
return '%s of %s>' % (repr(types.InstanceType)[:-1],
|
||||||
|
str(obj.__class__))
|
||||||
return t
|
return t
|
||||||
|
|
||||||
def deeptype(obj, maxLen=100, _visitedIds=None):
|
def deeptype(obj, maxLen=100, _visitedIds=None):
|
||||||
|
@ -35,6 +35,7 @@ import Loader
|
|||||||
import time
|
import time
|
||||||
from direct.fsm import ClassicFSM
|
from direct.fsm import ClassicFSM
|
||||||
from direct.fsm import State
|
from direct.fsm import State
|
||||||
|
from direct.showbase import ExceptionVarDump
|
||||||
import DirectObject
|
import DirectObject
|
||||||
import SfxPlayer
|
import SfxPlayer
|
||||||
if __debug__:
|
if __debug__:
|
||||||
@ -69,6 +70,8 @@ class ShowBase(DirectObject.DirectObject):
|
|||||||
notify = directNotify.newCategory("ShowBase")
|
notify = directNotify.newCategory("ShowBase")
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
if config.GetBool('want-variable-dump', 1):
|
||||||
|
ExceptionVarDump.install()
|
||||||
|
|
||||||
# Locate the directory containing the main program
|
# Locate the directory containing the main program
|
||||||
maindir=os.path.abspath(sys.path[0])
|
maindir=os.path.abspath(sys.path[0])
|
||||||
|
@ -14,6 +14,7 @@ from pandac.libpandaexpressModules import *
|
|||||||
from direct.directnotify.DirectNotifyGlobal import *
|
from direct.directnotify.DirectNotifyGlobal import *
|
||||||
from direct.showbase.PythonUtil import *
|
from direct.showbase.PythonUtil import *
|
||||||
from direct.showbase.MessengerGlobal import *
|
from direct.showbase.MessengerGlobal import *
|
||||||
|
from direct.showbase import ExceptionVarDump
|
||||||
import time
|
import time
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import string
|
import string
|
||||||
@ -981,6 +982,15 @@ class TaskManager:
|
|||||||
self.stop()
|
self.stop()
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
except Exception, e:
|
||||||
|
if self.extendedExceptions:
|
||||||
|
self.stop()
|
||||||
|
print_exc_plus()
|
||||||
|
else:
|
||||||
|
if (ExceptionVarDump.wantVariableDump and
|
||||||
|
ExceptionVarDump.dumpOnExceptionInit):
|
||||||
|
ExceptionVarDump._varDump__print(e)
|
||||||
|
raise
|
||||||
except:
|
except:
|
||||||
if self.extendedExceptions:
|
if self.extendedExceptions:
|
||||||
self.stop()
|
self.stop()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user