?? config.py
字號:
def isSimObjSequence(value): if not isinstance(value, (list, tuple)): return False for val in value: if not isNullPointer(val) and not isSimObject(val): return False return Truedef isNullPointer(value): return isinstance(value, NullSimObject)# 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# inherited class behavior (just like a class controls how instances# of that class are instantiated, and provides inherited instance# behavior).class MetaSimObject(type): # Attributes that can be set only at initialization time init_keywords = { 'abstract' : types.BooleanType, 'type' : types.StringType } # Attributes that can be set any time keywords = { 'check' : types.FunctionType, 'children' : types.ListType } # __new__ is called before __init__, and is where the statements # in the body of the class definition get loaded into the class's # __dict__. We intercept this to filter out parameter assignments # and only allow "private" attributes to be passed to the base # __new__ (starting with underscore). def __new__(mcls, name, bases, dict): # Copy "private" attributes (including special methods such as __new__) # to the official dict. Everything else goes in _init_dict to be # filtered in __init__. cls_dict = {} for key,val in dict.items(): if key.startswith('_'): cls_dict[key] = val del dict[key] cls_dict['_init_dict'] = dict return super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) # initialization def __init__(cls, name, bases, dict): super(MetaSimObject, cls).__init__(name, bases, dict) # initialize required attributes cls._params = multidict() cls._values = multidict() cls._anon_subclass_counter = 0 # We don't support multiple inheritance. If you want to, you # must fix multidict to deal with it properly. if len(bases) > 1: raise TypeError, "SimObjects do not support multiple inheritance" base = bases[0] if isinstance(base, MetaSimObject): cls._params.parent = base._params cls._values.parent = base._values # If your parent has a value in it that's a config node, clone # it. Do this now so if we update any of the values' # attributes we are updating the clone and not the original. for key,val in base._values.iteritems(): # don't clone if (1) we're about to overwrite it with # a local setting or (2) we've already cloned a copy # from an earlier (more derived) base if cls._init_dict.has_key(key) or cls._values.has_key(key): continue if isSimObject(val): cls._values[key] = val() elif isSimObjSequence(val) and len(val): cls._values[key] = [ v() for v in val ] # now process remaining _init_dict items for key,val in cls._init_dict.items(): if isinstance(val, (types.FunctionType, types.TypeType)): type.__setattr__(cls, key, val) # param descriptions elif isinstance(val, ParamDesc): cls._new_param(key, val) # init-time-only keywords elif cls.init_keywords.has_key(key): cls._set_keyword(key, val, cls.init_keywords[key]) # default: use normal path (ends up in __setattr__) else: setattr(cls, key, val) def _set_keyword(cls, keyword, val, kwtype): if not isinstance(val, kwtype): raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \\ (keyword, type(val), kwtype) if isinstance(val, types.FunctionType): val = classmethod(val) type.__setattr__(cls, keyword, val) def _new_param(cls, name, value): cls._params[name] = value if hasattr(value, 'default'): setattr(cls, name, value.default) # Set attribute (called on foo.attr = value when foo is an # instance of class cls). def __setattr__(cls, attr, value): # normal processing for private attributes if attr.startswith('_'): type.__setattr__(cls, attr, value) return if cls.keywords.has_key(attr): cls._set_keyword(attr, value, cls.keywords[attr]) return # must be SimObject param param = cls._params.get(attr, None) if param: # It's ok: set attribute by delegating to 'object' class. try: cls._values[attr] = param.convert(value) except Exception, e: msg = "%s\\nError setting param %s.%s to %s\\n" % \\ (e, cls.__name__, attr, value) e.args = (msg, ) raise # I would love to get rid of this elif isSimObject(value) or isSimObjSequence(value): cls._values[attr] = value else: raise AttributeError, \\ "Class %s has no parameter %s" % (cls.__name__, attr) def __getattr__(cls, attr): if cls._values.has_key(attr): return cls._values[attr] raise AttributeError, \\ "object '%s' has no attribute '%s'" % (cls.__name__, attr)# The ConfigNode class is the root of the special hierarchy. Most of# the code in this class deals with the configuration hierarchy itself# (parent/child node relationships).class SimObject(object): # Specify metaclass. Any class inheriting from SimObject will # get this metaclass. __metaclass__ = MetaSimObject def __init__(self, _value_parent = None, **kwargs): self._children = {} if _value_parent and type(_value_parent) != type(self): # this was called as a type conversion rather than a clone raise TypeError, "Cannot convert %s to %s" % \\ (_value_parent.__class__.__name__, self.__class__.__name__) if not _value_parent: _value_parent = self.__class__ # clone values self._values = multidict(_value_parent._values) for key,val in _value_parent._values.iteritems(): if isSimObject(val): setattr(self, key, val()) elif isSimObjSequence(val) and len(val): setattr(self, key, [ v() for v in val ]) # apply attribute assignments from keyword args, if any for key,val in kwargs.iteritems(): setattr(self, key, val) def __call__(self, **kwargs): return self.__class__(_value_parent = self, **kwargs) def __getattr__(self, attr): if self._values.has_key(attr): return self._values[attr] raise AttributeError, "object '%s' has no attribute '%s'" \\ % (self.__class__.__name__, attr) # Set attribute (called on foo.attr = value when foo is an # instance of class cls). def __setattr__(self, attr, value): # normal processing for private attributes if attr.startswith('_'): object.__setattr__(self, attr, value) return # must be SimObject param param = self._params.get(attr, None) if param: # It's ok: set attribute by delegating to 'object' class. try: value = param.convert(value) except Exception, e: msg = "%s\\nError setting param %s.%s to %s\\n" % \\ (e, self.__class__.__name__, attr, value) e.args = (msg, ) raise # I would love to get rid of this elif isSimObject(value) or isSimObjSequence(value): pass else: raise AttributeError, "Class %s has no parameter %s" \\ % (self.__class__.__name__, attr) # clear out old child with this name, if any self.clear_child(attr) if isSimObject(value): value.set_path(self, attr) elif isSimObjSequence(value): value = SimObjVector(value) [v.set_path(self, "%s%d" % (attr, i)) for i,v in enumerate(value)] self._values[attr] = value # this hack allows tacking a '[0]' onto parameters that may or may # not be vectors, and always getting the first element (e.g. cpus) def __getitem__(self, key): if key == 0: return self raise TypeError, "Non-zero index '%s' to SimObject" % key # clear out children with given name, even if it's a vector def clear_child(self, name): if not self._children.has_key(name): return child = self._children[name] if isinstance(child, SimObjVector): for i in xrange(len(child)): del self._children["s%d" % (name, i)] del self._children[name] def add_child(self, name, value): self._children[name] = value def set_path(self, parent, name): if not hasattr(self, '_parent'): self._parent = parent self._name = name parent.add_child(name, self) def path(self): if not hasattr(self, '_parent'): return 'root' ppath = self._parent.path() if ppath == 'root': return self._name return ppath + "." + self._name def __str__(self): return self.path() def ini_str(self): return self.path() def find_any(self, ptype): if isinstance(self, ptype): return self, True found_obj = None for child in self._children.itervalues(): if isinstance(child, ptype): if found_obj != None and child != found_obj: raise AttributeError, \\ 'parent.any matched more than one: %s %s' % \\ (found_obj.path, child.path) found_obj = child # search param space for pname,pdesc in self._params.iteritems(): if issubclass(pdesc.ptype, ptype): match_obj = self._values[pname] if found_obj != None and found_obj != match_obj: raise AttributeError, \\ 'parent.any matched more than one: %s' % obj.path found_obj = match_obj return found_obj, found_obj != None def unproxy(self, base): return self def print_ini(self): print '[' + self.path() + ']' # .ini section header if hasattr(self, 'type') and not isinstance(self, ParamContext): print 'type=%s' % self.type child_names = self._children.keys() child_names.sort() np_child_names = [c for c in child_names \\ if not isinstance(self._children[c], ParamContext)] if len(np_child_names): print 'children=%s' % ' '.join(np_child_names) param_names = self._params.keys() param_names.sort() for param in param_names: value = self._values.get(param, None) if value != None: if isproxy(value): try: value = value.unproxy(self) except: print >> sys.stderr, \\ "Error in unproxying param '%s' of %s" % \\ (param, self.path()) raise setattr(self, param, value) print '%s=%s' % (param, self._values[param].ini_str()) print # blank line between objects for child in child_names: self._children[child].print_ini() # generate output file for 'dot' to display as a pretty graph. # this code is currently broken. def outputDot(self, dot): label = "{%s|" % self.path if isSimObject(self.realtype): label += '%s|' % self.type if self.children: # instantiate children in same order they were added for # backward compatibility (else we can end up with cpu1 # before cpu0). for c in self.children: dot.add_edge(pydot.Edge(self.path,c.path, style="bold")) simobjs = [] for param in self.params: try: if param.value is None: raise AttributeError, 'Parameter with no value' value = param.value string = param.string(value) except Exception, e: msg = 'exception in %s:%s\\n%s' % (self.name, param.name, e) e.args = (msg, ) raise if isSimObject(param.ptype) and string != "Null": simobjs.append(string) else: label += '%s = %s\\\\n' % (param.name, string) for so in simobjs: label += "|<%s> %s" % (so, so) dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so, tailport="w")) label += '}' dot.add_node(pydot.Node(self.path,shape="Mrecord",label=label)) # recursively dump out children for c in self.children: c.outputDot(dot)class ParamContext(SimObject): pass####################################################################### Proxy object support.######################################################################class BaseProxy(object): def __init__(self, search_self, search_up): self._search_self = search_self self._search_up = search_up self._multiplier = None def __setattr__(self, attr, value): if not attr.startswith('_'): raise AttributeError, 'cannot set attribute on proxy object' super(BaseProxy, self).__setattr__(attr, value) # support multiplying proxies by constants def __mul__(self, other):
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -