#----------------------------------------------------------------------
# Name: RTTI.py
# Purpose:
#
# Author: Riaan Booysen
#
# Created: 1999
# RCS-ID: $Id: RTTI.py,v 1.20 2007/07/02 15:01:06 riaan Exp $
# Copyright: (c) 1999 - 2007 Riaan Booysen
# Licence: GPL
#----------------------------------------------------------------------
import sys, warnings
from types import *
import wx
warnings.filterwarnings('ignore', '', DeprecationWarning, 'RTTI')
def sort_proxy(self, other):
return self < other and -1 or self > other and 1 or 0
class PropertyWrapper:
# XXX This would be better implemented with subclassing
def __init__(self, name, rType, getter, setter):
""" Types: 'CtrlRoute', 'CompnRoute', 'EventRoute', 'NoneRoute',
'IndexRoute', 'NameRoute'
"""
self.name = name
self.routeType = rType
self.getter = getter
self.setter = setter
self.ctrl = None
self.compn = None
# Not used yet
self.setterName = ''
def __cmp__(self, other):
""" This is for sorting lists of PropertyWrappers """
# sort_proxy(self.name, other.name)
if self.name < other.name:
return -1
if self.name > other.name:
return 1
return 0
def __repr__(self):
return '<instance PropertyWrapper: %s, %s (%s, %s)'%(self.name,
self.routeType, self.getter, self.setter)
def connect(self, ctrl, compn):
self.ctrl = ctrl
self.compn = compn
def getValue(self, *params):
if self.routeType == 'CtrlRoute' and self.ctrl:
return self.getter(self.ctrl)
elif self.routeType == 'CompnRoute' and self.compn:
return self.getter(self.compn)
elif self.routeType == 'EventRoute' and self.compn and len(params):
return self.getter(params[0])
elif self.routeType == 'IndexRoute' and self.ctrl and len(params):
return self.getter(self.ctrl, params[0])
elif self.routeType == 'IdRoute' and self.ctrl and self.compn:
return self.getter(self.ctrl, self.compn.getDesignTimeWinId())
elif self.routeType == 'NameRoute':
return self.getter(self.name)
else:
return None
def setValue(self, value, *params):
if self.routeType == 'CtrlRoute' and self.ctrl:
self.setter(self.ctrl, value)
elif self.routeType == 'CompnRoute' and self.compn:
self.setter(value)
elif self.routeType == 'EventRoute' and self.compn and len(params):
self.setter(params[0], value)
elif self.routeType == 'IndexRoute' and self.ctrl and len(params):
self.setter(self.ctrl, params[0], value)
elif self.routeType == 'IdRoute' and self.ctrl and self.compn:
self.setter(self.ctrl, self.compn.getDesignTimeWinId(), value)
elif self.routeType == 'ReApplyRoute' and self.compn and len(params):
self.setter(*[self.ctrl], **params)
elif self.routeType == 'NameRoute':
return self.setter(self.name, value)
def getSetterName(self):
from types import FunctionType,MethodType
if self.setter:
if self.setterName:
return self.setterName
if type(self.setter) == FunctionType:
return self.setter.func_name
if type(self.setter) == MethodType:
return self.setter.im_func.func_name
else:
return ''
else:
return ''
_methodTypeCache = {}
def getPropList(obj, cmp):
"""
Function to extract sorted list of properties and getter/setter methods
from a given object and companion.
Property names that also occur in the Constructor list are stored under
the 'constructor' key
Vetoes are dangerous methods that should not be inspected
Returns:
{'constructor': [ PropertyWrapper, ... ],
'properties': [ PropertyWrapper, ... ] }
"""
def catalogProperty(name, methType, meths, constructors, propLst, constrLst):
if constructors.has_key(name):
constrLst.append(PropertyWrapper(name, methType, meths[0], meths[1]))
else:
propLst.append(PropertyWrapper(name, methType, meths[0], meths[1]))
#getPropList(obj, cmp):-
props = {}
props['Properties'] = {}
props['Methods'] = {}
props['Built-ins'] = {}
# traverse inheritance hierarchy
# populate property list
propLst = []
constrLst = []
# 2.4 2.5
if obj and (type(obj) is InstanceType or isinstance(obj, wx.Object)):
traverseAndBuildProps(props, cmp.vetoedMethods(), obj, obj.__class__)
# populate property list
if cmp:
constrNames = cmp.constructor()
else:
constrNames = {}
propNames = props['Properties'].keys()
propNames.sort()
for propName in propNames:
if cmp and propName in cmp.hideDesignTime():
continue
propMeths = props['Properties'][propName]
try:
catalogProperty(propName, 'CtrlRoute', propMeths,
constrNames, propLst, constrLst)
except:
catalogProperty(propName, 'NoneRoute', (None, None),
constrNames, propLst, constrLst)
if cmp:
xtraProps = cmp.properties()
propNames = xtraProps.keys()
propNames.sort()
for propName in propNames:
#if propName in cmp.hideDesignTime():
# continue
propMeths = xtraProps[propName]
try:
catalogProperty(propName, propMeths[0], propMeths[1:],
constrNames, propLst, constrLst)
except: pass
propLst.sort()
constrLst.sort()
else:
if cmp:
constrNames = cmp.constructor()
xtraProps = cmp.properties()
propNames = xtraProps.keys()
propNames.sort()
for propName in propNames:
propMeths = xtraProps[propName]
#try:
catalogProperty(propName, propMeths[0], propMeths[1:],
constrNames, propLst, constrLst)
#except:
# print 'prop error', sys.exc_info()
else:
pass #print 'Empty object', obj, cmp
return {'constructor': constrLst, 'properties': propLst}
def getMethodType(method, obj, Class):
""" classify methods according to prefix
return category, property name, getter, setter
"""
result = ('Methods', method, None, None)
try:
meth = getattr(obj, method)
except TypeError:
return result
except Exception:
#print obj, method
return result
if (type(meth) == MethodType):
func = meth.im_func
result = ('Methods', method, func, func)
prefix = method[:3]
property = method[3:]
getname = 'Get'+property
setname = 'Set'+property
try:
if (method[:2] == '__'):
result = ('Built-ins', method, func, func)
elif (prefix == 'Get') and hasattr(obj, setname) and property:
#see if getter breaks
v = func(obj)
result = ('Properties', property, func, getattr(obj, setname).im_func)
elif (prefix == 'Set') and hasattr(obj, getname) and property:
#see if getter breaks
getter = getattr(obj, getname).im_func
v = getter(obj)
result = ('Properties', property, getter, func)
except Exception, err:
pass
return result
def traverseAndBuildProps(props, vetoes, obj, Class):
for m in Class.__dict__.keys():
if m not in vetoes:
cat, name, methGetter, methSetter = \
getMethodType(m, obj, Class.__dict__)
if not props[cat].has_key(name):
props[cat][name] = (methGetter, methSetter)
for Cls in Class.__bases__:
traverseAndBuildProps(props, vetoes, obj, Cls)
if __name__ == '__main__':
wx.PySimpleApp()
f = wx.Frame(None, -1, 'asd')
c = wx.ComboBox(f, -1)
props = {'Properties': {}, 'Built-ins': {}, 'Methods': {}}
traverseAndBuildProps(props, [], c, c.__class__)
import pprint
pprint.pprint(props)
|