open_toontown_panda3d/direct/src/showbase/Finder.py

145 lines
4.8 KiB
Python

import types
import os
def findClassInModule(module, className, visited):
# Make sure you have not already visited this module
# to prevent recursion
if module in visited:
return None
# Ok, clear to proceed, add this module to the visited list
visited.append(module)
# print ('visiting: ' + `module`)
# Look in this module for classes and other modules
for key in module.__dict__.keys():
value = module.__dict__[key]
# If this is a class
if ((key != "_") and (type(value) == types.ClassType)):
# See if the name matches
if value.__name__ == className:
# It does! We found our class
return [value, module.__dict__]
# Its a module, recursively look into its namespace
elif (type(value) == types.ModuleType):
ret = findClassInModule(value, className, visited)
# If that recursion found it, return the goodies
if ret:
return ret
# Otherwise keep looking
# Well, after all that we did not find anything
return None
# Find a class named className somewhere in this namespace
def findClass(namespace, className):
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)):
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
return None
def rebindClass(builtins, filename):
file = open(filename)
lines = file.readlines()
curLine = 0
found = 0
foundLine = -1
foundChar = -1
for i in range(len(lines)):
line = lines[i]
if (line[0:6] == 'class '):
classHeader = line[6:]
# Look for a open paren if it does inherit
parenLoc = classHeader.find('(')
if parenLoc > 0:
className = classHeader[:parenLoc]
# print 'found className: ' + className
found = 1
foundLine = i
foundChar = parenLoc
else:
# Look for a colon if it does not inherit
colonLoc = classHeader.find(':')
if colonLoc > 0:
className = classHeader[:colonLoc]
# print 'found className: ' + className
found = 1
foundLine = i
foundChar = colonLoc
if not found:
print 'error: className not found'
return None
# Store the original real class
res = findClass(builtins, className)
if res:
realClass, realNameSpace = res
else:
print ('Error redinifing class: could not find class: ' + className)
return None
# Make a temp file in the home directory to execfile from
tmpfilename = os.path.join(os.getenv('HOME'), 'tmp_py_file')
tmpfile = open(tmpfilename, 'w')
# now write the class back to the file with the new class name
for i in range(len(lines)):
# if (i == foundLine):
# tmpfile.write(newline)
# else:
tmpfile.write(lines[i])
file.close()
tmpfile.close()
# Now execute that class def
execfile(tmpfilename, realNameSpace)
# Remove that temp file
os.remove(tmpfilename)
res = findClass(realNameSpace, className)
if res:
tmpClass, tmpNameSpace = res
else:
print ('Error redinifing class: could not find temp class')
return None
# Copy the functions that we just redefined into the real class
copyFuncs(tmpClass, realClass)
# Now make sure the original class is in that namespace, not our temp one
realNameSpace[className] = realClass
def copyFuncs(fromClass, toClass):
# Copy the functions from fromClass into toClass dictionary
for key in fromClass.__dict__.keys():
value = fromClass.__dict__[key]
if (type(value) == types.FunctionType):
oldFunc = toClass.__dict__[key]
newFunc = value
# Look in the messenger to see if this old function pointer
# is stored, and update it to the new function pointer
replaceMessengerFunc(oldFunc, newFunc)
toClass.__dict__[key] = newFunc
def replaceMessengerFunc(oldFunc, newFunc):
res = messenger.replaceMethod(oldFunc, newFunc)
if res:
print ('messenger replaced function: ' + newFunc.__name__)