moved ParamSet into ParamObj, added support for param kw values in ParamObj.__init__

This commit is contained in:
Darren Ranalli 2005-05-17 00:55:04 +00:00
parent b5e0705bfd
commit cfe3ca0ef7

View File

@ -761,7 +761,7 @@ class Stack:
return len(self.__list) return len(self.__list)
""" """
ParamSet/ParamObj ParamObj/ParamSet
================= =================
These two classes support you in the definition of a formal set of These two classes support you in the definition of a formal set of
@ -776,18 +776,21 @@ is risk of setting an illegal combination in the process of applying a new
set of values. set of values.
To make use of these classes, derive your object from ParamObj. Then define To make use of these classes, derive your object from ParamObj. Then define
a class that derives from ParamSet to define the object's parameters. The a 'ParamSet' subclass that derives from the parent class' 'ParamSet' class,
ParamObj class must declare a class-level reference to its ParamSet class, and define the object's parameters within its ParamSet class. (see examples
called 'ParamClass'. (See the example classes below.) below)
The ParamObj base class provides 'get' and 'set' functions for each The ParamObj base class provides 'get' and 'set' functions for each
parameter if they are not defined. parameter if they are not defined. These default implementations
respectively set the parameter value directly on the object, and expect the
value to be available in that location for retrieval.
Classes that derive from ParamObj must declare a 'get' and 'set' function Classes that derive from ParamObj can optionally declare a 'get' and 'set'
for each parameter. The setter should simply store the value in a location function for each parameter. The setter should simply store the value in a
where the getter can find it; it should not do any further processing based location where the getter can find it; it should not do any further
on the new parameter value. Further processing should be implemented in an processing based on the new parameter value. Further processing should be
'apply' function. The applier function is optional. implemented in an 'apply' function. The applier function is optional, and
there is no default implementation.
NOTE: the previous value of a parameter is available inside an apply NOTE: the previous value of a parameter is available inside an apply
function as 'self.getPriorValue()' function as 'self.getPriorValue()'
@ -852,14 +855,12 @@ EXAMPLE CLASSES
Here is an example of a class that uses ParamSet/ParamObj to manage its Here is an example of a class that uses ParamSet/ParamObj to manage its
parameters: parameters:
class CameraParams(ParamSet):
Params = {
'viewType': 'normal',
'fov': 60,
}
class Camera(ParamObj): class Camera(ParamObj):
ParamClass = CameraParams class ParamSet(ParamObj.ParamSet):
Params = {
'viewType': 'normal',
'fov': 60,
}
... ...
def getViewType(self): def getViewType(self):
@ -886,7 +887,7 @@ cam = Camera()
... ...
# set up for the cutscene # set up for the cutscene
savedSettings = CameraParams(cam) savedSettings = cam.ParamSet(cam)
cam.setViewType('closeup') cam.setViewType('closeup')
cam.setFov(90) cam.setFov(90)
... ...
@ -897,74 +898,83 @@ del savedSettings
""" """
class ParamSet:
# Base class for a container of parameter values. See documentation above.
Params = {
# base class does not define any parameters, but they would appear as
# 'name': value,
}
def __init__(self, *args, **kwArgs):
ParamSet._compileDefaultParams()
if len(args) == 1 and len(kwArgs) == 0:
# extract our params from an existing ParamObj instance
obj = args[0]
self.paramVals = {}
for param in self.getParams():
self.paramVals[param] = getSetter(obj, param, 'get')()
else:
assert len(args) == 0
if __debug__:
for arg in kwArgs.keys():
assert arg in self.getParams()
self.paramVals = dict(kwArgs)
def getValue(self, param):
if param in self.paramVals:
return self.paramVals[param]
return self._Params[param]
def applyTo(self, obj):
# Apply our entire set of params to a ParamObj
obj.lockParams()
for param in self.getParams():
getSetter(obj, param)(self.getValue(param))
obj.unlockParams()
# CLASS METHODS
def getParams(cls):
# returns safely-mutable list of param names
cls._compileDefaultParams()
return cls._Params.keys()
getParams = classmethod(getParams)
def getDefaultValue(cls, param):
cls._compileDefaultParams()
return cls._Params[param]
getDefaultValue = classmethod(getDefaultValue)
def _compileDefaultParams(cls):
if cls.__dict__.has_key('_Params'):
# we've already compiled the defaults for this class
return
bases = list(cls.__bases__)
# bring less-derived classes to the front
mostDerivedLast(bases)
cls._Params = {}
for c in (bases + [cls]):
# make sure this base has its dict of param defaults
c._compileDefaultParams()
if c.__dict__.has_key('Params'):
# apply this class' default param values to our dict
cls._Params.update(c.Params)
_compileDefaultParams = classmethod(_compileDefaultParams)
class ParamObj: class ParamObj:
# abstract base for classes that want to support a formal parameter # abstract base for classes that want to support a formal parameter
# set whose values may be queried, changed, 'bulk' changed, and # set whose values may be queried, changed, 'bulk' changed, and
# extracted/stored/applied all at once (see documentation above) # extracted/stored/applied all at once (see documentation above)
# derived class must override this to be the appropriate ParamSet subclass # ParamSet subclass: container of parameter values. Derived class must
ParamClass = ParamSet # derive a new ParamSet class if they wish to define new params. See
# documentation above.
class ParamSet:
Params = {
# base class does not define any parameters, but they would
# appear here as 'name': value,
}
def __init__(self, params=None): def __init__(self, *args, **kwArgs):
# If you pass in a ParamClass obj, its values will be applied to this self.__class__._compileDefaultParams()
if len(args) == 1 and len(kwArgs) == 0:
# extract our params from an existing ParamObj instance
obj = args[0]
self.paramVals = {}
for param in self.getParams():
self.paramVals[param] = getSetter(obj, param, 'get')()
else:
assert len(args) == 0
if __debug__:
for arg in kwArgs.keys():
assert arg in self.getParams()
self.paramVals = dict(kwArgs)
def getValue(self, param):
if param in self.paramVals:
return self.paramVals[param]
return self._Params[param]
def applyTo(self, obj):
# Apply our entire set of params to a ParamObj
obj.lockParams()
for param in self.getParams():
getSetter(obj, param)(self.getValue(param))
obj.unlockParams()
# CLASS METHODS
def getParams(cls):
# returns safely-mutable list of param names
cls._compileDefaultParams()
return cls._Params.keys()
getParams = classmethod(getParams)
def getDefaultValue(cls, param):
cls._compileDefaultParams()
return cls._Params[param]
getDefaultValue = classmethod(getDefaultValue)
def _compileDefaultParams(cls):
if cls.__dict__.has_key('_Params'):
# we've already compiled the defaults for this class
return
bases = list(cls.__bases__)
# bring less-derived classes to the front
mostDerivedLast(bases)
cls._Params = {}
for c in (bases + [cls]):
# make sure this base has its dict of param defaults
c._compileDefaultParams()
if c.__dict__.has_key('Params'):
# apply this class' default param values to our dict
cls._Params.update(c.Params)
_compileDefaultParams = classmethod(_compileDefaultParams)
# END PARAMSET SUBCLASS
def __init__(self, *args, **kwArgs):
# If you pass in a ParamSet obj, its values will be applied to this
# object in the constructor. # object in the constructor.
params = None
if len(args) == 1 and len(kwArgs) == 0:
# if there's one argument, assume that it's a ParamSet
params = args[0]
elif len(kwArgs) > 0:
assert len(args) == 0
# if we've got keyword arguments, make a ParamSet out of them
params = self.ParamSet(**kwArgs)
self._paramLockRefCount = 0 self._paramLockRefCount = 0
# this holds dictionaries of parameter values prior to the set that we # this holds dictionaries of parameter values prior to the set that we
# are performing # are performing
@ -1004,7 +1014,7 @@ class ParamObj:
self._priorValuesStack.pop() self._priorValuesStack.pop()
# insert stub funcs for param setters # insert stub funcs for param setters
for param in self.ParamClass.getParams(): for param in self.ParamSet.getParams():
setterName = getSetterName(param) setterName = getSetterName(param)
getterName = getSetterName(param, 'get') getterName = getSetterName(param, 'get')
@ -1017,9 +1027,10 @@ class ParamObj:
# is there a getter defined? # is there a getter defined?
if not hasattr(self, getterName): if not hasattr(self, getterName):
# no; provide the default. If there is no value set, return the default # no; provide the default. If there is no value set, return
# the default
def defaultGetter(self, param=param, def defaultGetter(self, param=param,
default=self.ParamClass.getDefaultValue(param)): default=self.ParamSet.getDefaultValue(param)):
return getattr(self, param, default) return getattr(self, param, default)
self.__class__.__dict__[getterName] = defaultGetter self.__class__.__dict__[getterName] = defaultGetter
@ -1033,14 +1044,15 @@ class ParamObj:
# install a setter stub that will a) call the real setter and # install a setter stub that will a) call the real setter and
# then the applier, or b) call the setter and queue the # then the applier, or b) call the setter and queue the
# applier, depending on whether our params are locked # applier, depending on whether our params are locked
self.__dict__[setterName] = Functor(setterStub, param, setterFunc, self) self.__dict__[setterName] = Functor(setterStub, param,
setterFunc, self)
if params is not None: if params is not None:
params.applyTo(self) params.applyTo(self)
def setDefaultParams(self): def setDefaultParams(self):
# set all the default parameters on ourself # set all the default parameters on ourself
self.ParamClass().applyTo(self) self.ParamSet().applyTo(self)
def lockParams(self): def lockParams(self):
self._paramLockRefCount += 1 self._paramLockRefCount += 1