Add some utility functions to ease handling
SimObjects and sequences of SimObjects in a uniform manner. --HG-- extra : convert_revision : 5db28b778c6b1ca63ad0a112ad7e92cd610f64d3
This commit is contained in:
parent
4ab8e881ed
commit
d3a5783523
|
@ -143,8 +143,8 @@ def isSimObjectClass(value):
|
|||
# happens if value is not a class at all
|
||||
return False
|
||||
|
||||
def isSimObjSequence(value):
|
||||
if not isinstance(value, (list, tuple)):
|
||||
def isSimObjectSequence(value):
|
||||
if not isinstance(value, (list, tuple)) or len(value) == 0:
|
||||
return False
|
||||
|
||||
for val in value:
|
||||
|
@ -153,8 +153,8 @@ def isSimObjSequence(value):
|
|||
|
||||
return True
|
||||
|
||||
def isSimObjClassSequence(value):
|
||||
if not isinstance(value, (list, tuple)):
|
||||
def isSimObjectClassSequence(value):
|
||||
if not isinstance(value, (list, tuple)) or len(value) == 0:
|
||||
return False
|
||||
|
||||
for val in value:
|
||||
|
@ -163,9 +163,31 @@ def isSimObjClassSequence(value):
|
|||
|
||||
return True
|
||||
|
||||
def isSimObjectOrSequence(value):
|
||||
return isSimObject(value) or isSimObjectSequence(value)
|
||||
|
||||
def isSimObjectClassOrSequence(value):
|
||||
return isSimObjectClass(value) or isSimObjectClassSequence(value)
|
||||
|
||||
def isNullPointer(value):
|
||||
return isinstance(value, NullSimObject)
|
||||
|
||||
# Apply method to object.
|
||||
# applyMethod(obj, 'meth', <args>) is equivalent to obj.meth(<args>)
|
||||
def applyMethod(obj, meth, *args, **kwargs):
|
||||
return getattr(obj, meth)(*args, **kwargs)
|
||||
|
||||
# If the first argument is an (non-sequence) object, apply the named
|
||||
# method with the given arguments. If the first argument is a
|
||||
# sequence, apply the method to each element of the sequence (a la
|
||||
# 'map').
|
||||
def applyOrMap(objOrSeq, meth, *args, **kwargs):
|
||||
if not isinstance(objOrSeq, (list, tuple)):
|
||||
return applyMethod(objOrSeq, meth, *args, **kwargs)
|
||||
else:
|
||||
return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq]
|
||||
|
||||
|
||||
# The metaclass for ConfigNode (and thus for everything that derives
|
||||
# from ConfigNode, including SimObject). This class controls how new
|
||||
# classes that derive from ConfigNode are instantiated, and provides
|
||||
|
@ -255,21 +277,15 @@ class MetaSimObject(type):
|
|||
# Existing classes should not have any instance values, so
|
||||
# these can only occur at the lowest level dict (the
|
||||
# parameters just being set in this class definition).
|
||||
if isSimObject(val):
|
||||
if isSimObjectOrSequence(val):
|
||||
assert(val == cls._values.local[key])
|
||||
cls._values[key] = val.makeClass(memo)
|
||||
elif isSimObjSequence(val) and len(val):
|
||||
assert(val == cls._values.local[key])
|
||||
cls._values[key] = [ v.makeClass(memo) for v in val ]
|
||||
cls._values[key] = applyOrMap(val, 'makeClass', memo)
|
||||
# SimObject classes need to be subclassed so that
|
||||
# parameters that get set at this level only affect this
|
||||
# level and derivatives.
|
||||
elif isSimObjectClass(val):
|
||||
elif isSimObjectClassOrSequence(val):
|
||||
assert(not cls._values.local.has_key(key))
|
||||
cls._values[key] = val.makeSubclass({}, memo)
|
||||
elif isSimObjClassSequence(val) and len(val):
|
||||
assert(not cls._values.local.has_key(key))
|
||||
cls._values[key] = [ v.makeSubclass({}, memo) for v in val ]
|
||||
cls._values[key] = applyOrMap(val, 'makeSubclass', {}, memo)
|
||||
|
||||
|
||||
def _set_keyword(cls, keyword, val, kwtype):
|
||||
|
@ -301,8 +317,7 @@ class MetaSimObject(type):
|
|||
param = cls._params.get(attr, None)
|
||||
if param:
|
||||
# It's ok: set attribute by delegating to 'object' class.
|
||||
if (isSimObject(value) or isSimObjSequence(value)) \
|
||||
and cls._instantiated:
|
||||
if isSimObjectOrSequence(value) and cls._instantiated:
|
||||
raise AttributeError, \
|
||||
"Cannot set SimObject parameter '%s' after\n" \
|
||||
" class %s has been instantiated or subclassed" \
|
||||
|
@ -315,7 +330,7 @@ class MetaSimObject(type):
|
|||
e.args = (msg, )
|
||||
raise
|
||||
# I would love to get rid of this
|
||||
elif isSimObject(value) or isSimObjSequence(value):
|
||||
elif isSimObjectOrSequence(value):
|
||||
cls._values[attr] = value
|
||||
else:
|
||||
raise AttributeError, \
|
||||
|
@ -407,7 +422,7 @@ class SimObject(object):
|
|||
for key,val in self.__class__._values.iteritems():
|
||||
if isSimObjectClass(val):
|
||||
setattr(self, key, val(_memo))
|
||||
elif isSimObjClassSequence(val) and len(val):
|
||||
elif isSimObjectClassSequence(val) and len(val):
|
||||
setattr(self, key, [ v(_memo) for v in val ])
|
||||
# apply attribute assignments from keyword args, if any
|
||||
for key,val in kwargs.iteritems():
|
||||
|
@ -454,7 +469,7 @@ class SimObject(object):
|
|||
e.args = (msg, )
|
||||
raise
|
||||
# I would love to get rid of this
|
||||
elif isSimObject(value) or isSimObjSequence(value):
|
||||
elif isSimObjectOrSequence(value):
|
||||
pass
|
||||
else:
|
||||
raise AttributeError, "Class %s has no parameter %s" \
|
||||
|
@ -465,7 +480,7 @@ class SimObject(object):
|
|||
|
||||
if isSimObject(value):
|
||||
value.set_path(self, attr)
|
||||
elif isSimObjSequence(value):
|
||||
elif isSimObjectSequence(value):
|
||||
value = SimObjVector(value)
|
||||
[v.set_path(self, "%s%d" % (attr, i)) for i,v in enumerate(value)]
|
||||
|
||||
|
@ -888,7 +903,7 @@ class VectorParamDesc(ParamDesc):
|
|||
if isinstance(value, (list, tuple)):
|
||||
# list: coerce each element into new list
|
||||
tmp_list = [ ParamDesc.convert(self, v) for v in value ]
|
||||
if isSimObjSequence(tmp_list):
|
||||
if isSimObjectSequence(tmp_list):
|
||||
return SimObjVector(tmp_list)
|
||||
else:
|
||||
return VectorParamValue(tmp_list)
|
||||
|
|
Loading…
Reference in a new issue