|
@@ -1,69 +1,31 @@
|
|
|
-
|
|
|
|
|
|
|
+import time
|
|
|
import types
|
|
import types
|
|
|
import os
|
|
import os
|
|
|
import new
|
|
import new
|
|
|
-
|
|
|
|
|
-def findClassInModule(module, className, visited):
|
|
|
|
|
- # Make sure you have not already visited this module
|
|
|
|
|
- # to prevent recursion
|
|
|
|
|
- if visited.has_key(module):
|
|
|
|
|
- return None
|
|
|
|
|
- # Ok, clear to proceed, add this module to the visited list
|
|
|
|
|
- visited[module] = 1
|
|
|
|
|
- # print ('visiting: ' + `module`)
|
|
|
|
|
-
|
|
|
|
|
- # First see if we are in the dict at this level
|
|
|
|
|
- classObj = module.__dict__.get(className)
|
|
|
|
|
- if classObj and ((type(classObj) == types.ClassType) or
|
|
|
|
|
- (type(classObj) == types.TypeType)):
|
|
|
|
|
- if classObj.__module__ == module.__name__:
|
|
|
|
|
- return [classObj, module.__dict__]
|
|
|
|
|
- else:
|
|
|
|
|
- # print "Must have found a module that imported this class", classObj, module
|
|
|
|
|
- pass
|
|
|
|
|
-
|
|
|
|
|
- # Now filter out all the modules and iterate through them
|
|
|
|
|
- moduleList = filter(lambda value: type(value) == types.ModuleType, module.__dict__.values())
|
|
|
|
|
- for moduleObj in moduleList:
|
|
|
|
|
- ret = findClassInModule(moduleObj, className, visited)
|
|
|
|
|
- # If that recursion found it, return the goodies
|
|
|
|
|
- if ret:
|
|
|
|
|
- return ret
|
|
|
|
|
-
|
|
|
|
|
- # Well, after all that we did not find anything
|
|
|
|
|
- return None
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-# Find a class named className somewhere in this namespace
|
|
|
|
|
-def findClass(namespace, className):
|
|
|
|
|
-
|
|
|
|
|
- # First see if we are in the namespace
|
|
|
|
|
- classObj = namespace.get(className)
|
|
|
|
|
- # print classObj, type(classObj)
|
|
|
|
|
- if classObj and ((type(classObj) == types.ClassType) or
|
|
|
|
|
- (type(classObj) == types.TypeType)):
|
|
|
|
|
- return [classObj, namespace]
|
|
|
|
|
-
|
|
|
|
|
- for key in namespace.keys():
|
|
|
|
|
- value = namespace[key]
|
|
|
|
|
- # If we found a class, see if it matches classname
|
|
|
|
|
- # Make sure we do not match "_"
|
|
|
|
|
- if ((key != "_") and ((type(value) == types.ClassType) or
|
|
|
|
|
- (type(value) == types.TypeType))):
|
|
|
|
|
- if value.__name__ == className:
|
|
|
|
|
- # It does, that was easy!
|
|
|
|
|
- return [value, namespace]
|
|
|
|
|
- # Look in all the modules in this namespace
|
|
|
|
|
- elif (type(value) == types.ModuleType):
|
|
|
|
|
- ret = findClassInModule(value, className, {})
|
|
|
|
|
- # If we found it return the goodies
|
|
|
|
|
- if ret:
|
|
|
|
|
- return ret
|
|
|
|
|
- # Otherwise keep looking
|
|
|
|
|
- # Nope, not in there
|
|
|
|
|
|
|
+import sys
|
|
|
|
|
+
|
|
|
|
|
+def findClass(className):
|
|
|
|
|
+ """
|
|
|
|
|
+ Look in sys.modules dictionary for a module that defines a class
|
|
|
|
|
+ with this className.
|
|
|
|
|
+ """
|
|
|
|
|
+ for moduleName, module in sys.modules.items():
|
|
|
|
|
+ # Some modules are None for some reason
|
|
|
|
|
+ if module:
|
|
|
|
|
+ # print "Searching in ", moduleName
|
|
|
|
|
+ classObj = module.__dict__.get(className)
|
|
|
|
|
+ # If this modules defines some object called classname and the
|
|
|
|
|
+ # object is a class or type definition and that class's module
|
|
|
|
|
+ # is the same as the module we are looking in, then we found
|
|
|
|
|
+ # the matching class and a good module namespace to redefine
|
|
|
|
|
+ # our class in.
|
|
|
|
|
+ if (classObj and
|
|
|
|
|
+ ((type(classObj) == types.ClassType) or
|
|
|
|
|
+ (type(classObj) == types.TypeType)) and
|
|
|
|
|
+ (classObj.__module__ == moduleName)):
|
|
|
|
|
+ return [classObj, module.__dict__]
|
|
|
return None
|
|
return None
|
|
|
|
|
|
|
|
-
|
|
|
|
|
def rebindClass(builtinGlobals, filename):
|
|
def rebindClass(builtinGlobals, filename):
|
|
|
file = open(filename, 'r')
|
|
file = open(filename, 'r')
|
|
|
lines = file.readlines()
|
|
lines = file.readlines()
|
|
@@ -83,96 +45,135 @@ def rebindClass(builtinGlobals, filename):
|
|
|
className = classHeader[:colonLoc]
|
|
className = classHeader[:colonLoc]
|
|
|
else:
|
|
else:
|
|
|
print 'error: className not found'
|
|
print 'error: className not found'
|
|
|
|
|
+ # Remove that temp file
|
|
|
|
|
+ file.close()
|
|
|
|
|
+ os.remove(filename)
|
|
|
return
|
|
return
|
|
|
print 'Rebinding class name: ' + className
|
|
print 'Rebinding class name: ' + className
|
|
|
break
|
|
break
|
|
|
|
|
|
|
|
- # Store the original real class
|
|
|
|
|
- res = findClass(builtinGlobals, className)
|
|
|
|
|
- if res:
|
|
|
|
|
- realClass, realNameSpace = res
|
|
|
|
|
- else:
|
|
|
|
|
- # print ('Warning: could not find class, defining new class in builtins: ' + className)
|
|
|
|
|
- # Now execute that class def
|
|
|
|
|
- # execfile(filename, builtinGlobals)
|
|
|
|
|
- print ('Warning: Finder could not find class, try importing the file first')
|
|
|
|
|
- # Remove that temp file
|
|
|
|
|
|
|
+ # Try to find the original class with this class name
|
|
|
|
|
+ res = findClass(className)
|
|
|
|
|
+
|
|
|
|
|
+ if not res:
|
|
|
|
|
+ print ('Warning: Finder could not find class')
|
|
|
|
|
+ # Remove the temp file we made
|
|
|
file.close()
|
|
file.close()
|
|
|
os.remove(filename)
|
|
os.remove(filename)
|
|
|
return
|
|
return
|
|
|
|
|
|
|
|
- # Now execute that class def
|
|
|
|
|
|
|
+ # Store the original real class
|
|
|
|
|
+ realClass, realNameSpace = res
|
|
|
|
|
+
|
|
|
|
|
+ # Now execute that class def in this namespace
|
|
|
execfile(filename, realNameSpace)
|
|
execfile(filename, realNameSpace)
|
|
|
- # Remove that temp file
|
|
|
|
|
- file.close()
|
|
|
|
|
- os.remove(filename)
|
|
|
|
|
|
|
|
|
|
|
|
+ # That execfile should have created a new class obj in that namespace
|
|
|
tmpClass = realNameSpace[className]
|
|
tmpClass = realNameSpace[className]
|
|
|
|
|
|
|
|
# Copy the functions that we just redefined into the real class
|
|
# Copy the functions that we just redefined into the real class
|
|
|
copyFuncs(tmpClass, realClass)
|
|
copyFuncs(tmpClass, realClass)
|
|
|
|
|
|
|
|
- # Now make sure the original class is in that namespace, not our temp one
|
|
|
|
|
|
|
+ # Now make sure the original class is in that namespace,
|
|
|
|
|
+ # not our temp one from the execfile. This will help us preserve
|
|
|
|
|
+ # class variables and other state on the original class.
|
|
|
realNameSpace[className] = realClass
|
|
realNameSpace[className] = realClass
|
|
|
|
|
+
|
|
|
|
|
+ # Remove the temp file we made
|
|
|
|
|
+ file.close()
|
|
|
|
|
+ os.remove(filename)
|
|
|
|
|
|
|
|
print (' Finished rebind')
|
|
print (' Finished rebind')
|
|
|
|
|
|
|
|
|
|
|
|
|
def copyFuncs(fromClass, toClass):
|
|
def copyFuncs(fromClass, toClass):
|
|
|
|
|
+ replaceFuncList = []
|
|
|
|
|
+ newFuncList = []
|
|
|
|
|
+
|
|
|
# Copy the functions from fromClass into toClass dictionary
|
|
# Copy the functions from fromClass into toClass dictionary
|
|
|
- for key in fromClass.__dict__.keys():
|
|
|
|
|
- value = fromClass.__dict__[key]
|
|
|
|
|
- if (type(value) == types.FunctionType):
|
|
|
|
|
- newFunc = value
|
|
|
|
|
|
|
+ for funcName, newFunc in fromClass.__dict__.items():
|
|
|
|
|
+ # Filter out for functions
|
|
|
|
|
+ if (type(newFunc) == types.FunctionType):
|
|
|
# See if we already have a function with this name
|
|
# See if we already have a function with this name
|
|
|
- if toClass.__dict__.has_key(key):
|
|
|
|
|
- # Look in the messenger and taskMgr to see if this
|
|
|
|
|
- # old function pointer is stored there,
|
|
|
|
|
- # and update it to the new function pointer
|
|
|
|
|
- oldFunc = toClass.__dict__[key]
|
|
|
|
|
- replaceMessengerFunc(oldFunc, newFunc)
|
|
|
|
|
- replaceTaskMgrFunc(oldFunc, newFunc)
|
|
|
|
|
- replaceStateFunc(oldFunc, newFunc)
|
|
|
|
|
- replaceTcrFunc(oldFunc, newFunc)
|
|
|
|
|
- # You cannot assign directly to the dict with new style classes
|
|
|
|
|
- # toClass.__dict__[key] = newFunc
|
|
|
|
|
- # Instead we will use setattr
|
|
|
|
|
- setattr(toClass, key, newFunc)
|
|
|
|
|
-
|
|
|
|
|
-def replaceMessengerFunc(oldFunc, newFunc):
|
|
|
|
|
|
|
+ oldFunc = toClass.__dict__.get(funcName)
|
|
|
|
|
+ if oldFunc:
|
|
|
|
|
+ replaceFuncList.append((oldFunc, funcName, newFunc))
|
|
|
|
|
+ else:
|
|
|
|
|
+ newFuncList.append((funcName, newFunc))
|
|
|
|
|
+
|
|
|
|
|
+ # Look in the messenger, taskMgr, and other globals that store func
|
|
|
|
|
+ # pointers to see if this old function pointer is stored there, and
|
|
|
|
|
+ # update it to the new function pointer.
|
|
|
|
|
+ replaceMessengerFunc(replaceFuncList)
|
|
|
|
|
+ replaceTaskMgrFunc(replaceFuncList)
|
|
|
|
|
+ replaceStateFunc(replaceFuncList)
|
|
|
|
|
+ replaceCRFunc(replaceFuncList)
|
|
|
|
|
+ replaceAIRFunc(replaceFuncList)
|
|
|
|
|
+ replaceIvalFunc(replaceFuncList)
|
|
|
|
|
+
|
|
|
|
|
+ # Now that we've the globals funcs, actually swap the pointers in
|
|
|
|
|
+ # the new class to the new functions
|
|
|
|
|
+ for oldFunc, funcName, newFunc in replaceFuncList:
|
|
|
|
|
+ # print "replacing old func: ", oldFunc, funcName, newFunc
|
|
|
|
|
+ setattr(toClass, funcName, newFunc)
|
|
|
|
|
+ # Add the brand new functions too
|
|
|
|
|
+ for funcName, newFunc in newFuncList:
|
|
|
|
|
+ # print "adding new func: ", oldFunc, funcName, newFunc
|
|
|
|
|
+ setattr(toClass, funcName, newFunc)
|
|
|
|
|
+
|
|
|
|
|
+def replaceMessengerFunc(replaceFuncList):
|
|
|
try:
|
|
try:
|
|
|
messenger
|
|
messenger
|
|
|
except:
|
|
except:
|
|
|
return
|
|
return
|
|
|
- res = messenger.replaceMethod(oldFunc, newFunc)
|
|
|
|
|
- if res:
|
|
|
|
|
- print 'replaced %d messenger functions: %s' % (res, newFunc.__name__)
|
|
|
|
|
|
|
+ for oldFunc, funcName, newFunc in replaceFuncList:
|
|
|
|
|
+ res = messenger.replaceMethod(oldFunc, newFunc)
|
|
|
|
|
+ if res:
|
|
|
|
|
+ print ('replaced %s messenger function(s): %s' % (res, funcName))
|
|
|
|
|
|
|
|
-def replaceTaskMgrFunc(oldFunc, newFunc):
|
|
|
|
|
|
|
+def replaceTaskMgrFunc(replaceFuncList):
|
|
|
try:
|
|
try:
|
|
|
taskMgr
|
|
taskMgr
|
|
|
except:
|
|
except:
|
|
|
return
|
|
return
|
|
|
- res = taskMgr.replaceMethod(oldFunc, newFunc)
|
|
|
|
|
- if res:
|
|
|
|
|
- print ('replaced taskMgr function: ' + newFunc.__name__)
|
|
|
|
|
-
|
|
|
|
|
-def replaceStateFunc(oldFunc, newFunc):
|
|
|
|
|
- from direct.fsm import State
|
|
|
|
|
- res = State.redefineEnterFunc(oldFunc, newFunc)
|
|
|
|
|
- if res:
|
|
|
|
|
- print ('replaced state enter function: ' + newFunc.__name__)
|
|
|
|
|
- res = State.redefineExitFunc(oldFunc, newFunc)
|
|
|
|
|
- if res:
|
|
|
|
|
- print ('replaced state exit function: ' + newFunc.__name__)
|
|
|
|
|
-
|
|
|
|
|
-def replaceTcrFunc(oldFunc, newFunc):
|
|
|
|
|
|
|
+ for oldFunc, funcName, newFunc in replaceFuncList:
|
|
|
|
|
+ if taskMgr.replaceMethod(oldFunc, newFunc):
|
|
|
|
|
+ print ('replaced taskMgr function: %s' % funcName)
|
|
|
|
|
+
|
|
|
|
|
+def replaceStateFunc(replaceFuncList):
|
|
|
|
|
+ if not sys.modules.get('direct.fsm.State'):
|
|
|
|
|
+ return
|
|
|
|
|
+ from direct.fsm.State import State
|
|
|
|
|
+ for oldFunc, funcName, newFunc in replaceFuncList:
|
|
|
|
|
+ res = State.replaceMethod(oldFunc, newFunc)
|
|
|
|
|
+ if res:
|
|
|
|
|
+ print ('replaced %s FSM transition function(s): %s' % (res, funcName))
|
|
|
|
|
+
|
|
|
|
|
+def replaceCRFunc(replaceFuncList):
|
|
|
|
|
+ try:
|
|
|
|
|
+ base.cr
|
|
|
|
|
+ except:
|
|
|
|
|
+ return
|
|
|
|
|
+ for oldFunc, funcName, newFunc in replaceFuncList:
|
|
|
|
|
+ if base.cr.replaceMethod(oldFunc, newFunc):
|
|
|
|
|
+ print ('replaced DistributedObject function: %s' % funcName)
|
|
|
|
|
+
|
|
|
|
|
+def replaceAIRFunc(replaceFuncList):
|
|
|
try:
|
|
try:
|
|
|
- res = base.cr.replaceMethod(oldFunc, newFunc)
|
|
|
|
|
|
|
+ simbase.air
|
|
|
except:
|
|
except:
|
|
|
- try:
|
|
|
|
|
- res = simbase.air.replaceMethod(oldFunc, newFunc)
|
|
|
|
|
- except:
|
|
|
|
|
- res = None
|
|
|
|
|
- if res:
|
|
|
|
|
- print ('replaced DistributedObject function: ' + newFunc.__name__)
|
|
|
|
|
|
|
+ return
|
|
|
|
|
+ for oldFunc, funcName, newFunc in replaceFuncList:
|
|
|
|
|
+ if simbase.air.replaceMethod(oldFunc, newFunc):
|
|
|
|
|
+ print ('replaced DistributedObject function: %s' % funcName)
|
|
|
|
|
+
|
|
|
|
|
+def replaceIvalFunc(replaceFuncList):
|
|
|
|
|
+ # Make sure we have imported IntervalManager and thus created
|
|
|
|
|
+ # a global ivalMgr.
|
|
|
|
|
+ if not sys.modules.get('direct.interval.IntervalManager'):
|
|
|
|
|
+ return
|
|
|
|
|
+ from direct.interval.FunctionInterval import FunctionInterval
|
|
|
|
|
+ for oldFunc, funcName, newFunc in replaceFuncList:
|
|
|
|
|
+ res = FunctionInterval.replaceMethod(oldFunc, newFunc)
|
|
|
|
|
+ if res:
|
|
|
|
|
+ print ('replaced %s interval function(s): %s' % (res, funcName))
|