Python Introspection and Documentation

April 12th, 2005 by Patrick Boucher - Viewed 1809 times - Popularity: 6% [?]




I”ve been outside XSI for a while writing up and maintaining some buisness productivity applications for the shop I work for. On top of that I have to prepare for NAB next week where I”ll be going with a few colleagues. I did however decide that I should take a few seconds to do a quick post with some pearls of wisdom recently posted by Jerry Gamache (Python ace and Softimage employee) on the Softimage|XSI mailing list. These tricks are way too precious to stay hidden in one place!

Check these out… Thanks Jerry!

Introspection

The following function lists the names of all properties and methods a dynamically dispatched COM object might have. You can give it any object XSI might return to you and it will spit out a list of things you can find in that object. One neat way of figuring out what it can do for you is to paste it in your script editor, select random stuff in a scene and run Application.LogMessage(GetFunctions(Application.Selection[0])).


def GetFunctions(dynDisp):
"""returns a sorted and unique list of all functions defined in a dynamic dispatch"""
dict = {}
try:
for iTI in xrange(0,dynDisp._oleobj_.GetTypeInfoCount()):
typeInfo = dynDisp._oleobj_.GetTypeInfo(iTI)
typeAttr = typeInfo.GetTypeAttr()
for iFun in xrange(0,typeAttr.cFuncs):
funDesc = typeInfo.GetFuncDesc(iFun)
name = typeInfo.GetNames(funDesc.memid)[0]
dict[name] = 1
except:
pass # Object is not the dynamic dispatch I knew
ret = dict.keys()
ret.sort()
return ret

Documentation

This next one builds on the introspection trick. It basically uses the same techniques to go into the object but this time pulls out the equivalent of docstrings. You can call it by providing an object and optinally a method name:

Application.LogMessage(GetDocumentation(Application))
or
Application.LogMessage(GetDocumentation(Application, "StatusBar"))

Again using this with a selection can give you nice insights into what is available to you as a scripter. I particularly like this one because it lists method arguments as well as giving you the documentation. It could even be extended to give you the return type. I”ll have to see if I can elevate my skills to the appropriate level to do so. ;)


def FormatDocumentation(typeInfo, funDesc):
nameAndParms = typeInfo.GetNames(funDesc.memid)
docum = typeInfo.GetDocumentation(funDesc.memid)
import pythoncom
# This one differentiates between "functions" and "accessors"
if funDesc.invkind == pythoncom.INVOKE_FUNC:
docStr = nameAndParms[0] + "(" + ",".join(nameAndParms[1:]) + ")\n"
else:
docStr = nameAndParms[0] + "\n"
if docum[1]:
docStr += "\t" + docum[1]
return docStr


def GetDocumentation( dynDisp, funcName = None ):
allTypeInfoDoc = []
for iTI in xrange(0,dynDisp._oleobj_.GetTypeInfoCount()):
typeInfo = dynDisp._oleobj_.GetTypeInfo(iTI)
typeAttr = typeInfo.GetTypeAttr()
if funcName:
for iFun in xrange(0,typeAttr.cFuncs):
funDesc = typeInfo.GetFuncDesc(iFun)
name = typeInfo.GetNames(funDesc.memid)[0]
if name.upper() == funcName.upper():
return FormatDocumentation(typeInfo, funDesc)
else:
dict = {}
className = dynDisp._oleobj_.GetTypeInfo(0).GetDocumentation(-1)
classDoc = "class %s \n\t%s\n\n"%(className[0],className[1])
allFuncDoc = []
for iFun in xrange(0,typeAttr.cFuncs):
funDesc = typeInfo.GetFuncDesc(iFun)
name = typeInfo.GetNames(funDesc.memid)[0]
if not dict.has_key(name):
dict[name] = 1
allFuncDoc.append(FormatDocumentation(typeInfo, funDesc))
allFuncDoc.sort()
allTypeInfoDoc.append(classDoc + "\n".join(allFuncDoc))
if funcName:
return "Documentation not found for %s"%(funcName,)
else:
return "\n".join(allTypeInfoDoc)

Have fun!

Popularity: 6% [?]

Leave a Reply