Merge ktlim@zizzer.eecs.umich.edu:/bk/m5
into zamp.eecs.umich.edu:/z/ktlim2/m5 --HG-- extra : convert_revision : 0c750652cc2b59946160994d53c921cb021ceef4
This commit is contained in:
commit
2ec918362e
5 changed files with 246 additions and 152 deletions
|
@ -1,14 +1,14 @@
|
||||||
import sys, os
|
import sys, os
|
||||||
|
|
||||||
# the mpy import code is added to the global import meta_path as a
|
|
||||||
# side effect of this import
|
|
||||||
from mpy_importer import AddToPath, LoadMpyFile
|
|
||||||
|
|
||||||
# define this here so we can use it right away if necessary
|
# define this here so we can use it right away if necessary
|
||||||
def panic(string):
|
def panic(string):
|
||||||
print >>sys.stderr, 'panic:', string
|
print >>sys.stderr, 'panic:', string
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# the mpy import code is added to the global import meta_path as a
|
||||||
|
# side effect of this import
|
||||||
|
from mpy_importer import AddToPath, LoadMpyFile
|
||||||
|
|
||||||
# find the m5 compile options: must be specified as a dict in
|
# find the m5 compile options: must be specified as a dict in
|
||||||
# __main__.m5_build_env.
|
# __main__.m5_build_env.
|
||||||
import __main__
|
import __main__
|
||||||
|
|
|
@ -29,6 +29,7 @@ import os, re, sys, types, inspect
|
||||||
|
|
||||||
from m5 import panic
|
from m5 import panic
|
||||||
from convert import *
|
from convert import *
|
||||||
|
from multidict import multidict
|
||||||
|
|
||||||
noDot = False
|
noDot = False
|
||||||
try:
|
try:
|
||||||
|
@ -151,8 +152,11 @@ class Proxy(object):
|
||||||
self._multiplier = None
|
self._multiplier = None
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
|
# python uses __bases__ internally for inheritance
|
||||||
if attr == '__bases__':
|
if attr == '__bases__':
|
||||||
return super(Proxy, self).__getattr__(self, attr)
|
return super(Proxy, self).__getattr__(self, attr)
|
||||||
|
if (self._path == None):
|
||||||
|
panic("Can't add attributes to 'any' proxy")
|
||||||
self._path.append((attr,None))
|
self._path.append((attr,None))
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -198,6 +202,7 @@ class Proxy(object):
|
||||||
raise AttributeError, \
|
raise AttributeError, \
|
||||||
'Parent of %s type %s not found at path %s' \
|
'Parent of %s type %s not found at path %s' \
|
||||||
% (base.name, ptype, self._path)
|
% (base.name, ptype, self._path)
|
||||||
|
|
||||||
result, done = obj.find(ptype, self._path)
|
result, done = obj.find(ptype, self._path)
|
||||||
obj = obj.parent
|
obj = obj.parent
|
||||||
|
|
||||||
|
@ -322,17 +327,20 @@ class MetaConfigNode(type):
|
||||||
super(MetaConfigNode, cls).__init__(name, bases, dict)
|
super(MetaConfigNode, cls).__init__(name, bases, dict)
|
||||||
|
|
||||||
# initialize required attributes
|
# initialize required attributes
|
||||||
cls._params = {}
|
cls._params = multidict()
|
||||||
cls._values = {}
|
cls._values = multidict()
|
||||||
cls._param_types = {}
|
cls._param_types = {}
|
||||||
cls._bases = [c for c in cls.__mro__ if isConfigNode(c)]
|
cls._bases = [c for c in cls.__mro__ if isConfigNode(c)]
|
||||||
cls._anon_subclass_counter = 0
|
cls._anon_subclass_counter = 0
|
||||||
|
|
||||||
# If your parent has a value in it that's a config node, clone
|
# We don't support multiple inheritence. If you want to, you
|
||||||
# it. Do this now so if we update any of the values'
|
# must fix multidict to deal with it properly.
|
||||||
# attributes we are updating the clone and not the original.
|
cnbase = [ base for base in bases if isConfigNode(base) ]
|
||||||
for base in cls._bases:
|
if len(cnbase) == 1:
|
||||||
for key,val in base._values.iteritems():
|
# 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 cnbase[0]._values.iteritems():
|
||||||
|
|
||||||
# don't clone if (1) we're about to overwrite it with
|
# don't clone if (1) we're about to overwrite it with
|
||||||
# a local setting or (2) we've already cloned a copy
|
# a local setting or (2) we've already cloned a copy
|
||||||
|
@ -342,10 +350,17 @@ class MetaConfigNode(type):
|
||||||
|
|
||||||
if isConfigNode(val):
|
if isConfigNode(val):
|
||||||
cls._values[key] = val()
|
cls._values[key] = val()
|
||||||
elif isSimObjSequence(val):
|
elif isSimObjSequence(val) and len(val):
|
||||||
cls._values[key] = [ v() for v in val ]
|
cls._values[key] = [ v() for v in val ]
|
||||||
elif isNullPointer(val):
|
|
||||||
cls._values[key] = val
|
cls._params.parent = cnbase[0]._params
|
||||||
|
cls._values.parent = cnbase[0]._values
|
||||||
|
|
||||||
|
elif len(cnbase) > 1:
|
||||||
|
panic("""\
|
||||||
|
The config hierarchy only supports single inheritence of SimObject
|
||||||
|
classes. You're trying to derive from:
|
||||||
|
%s""" % str(cnbase))
|
||||||
|
|
||||||
# process param types from _init_dict, as these may be needed
|
# process param types from _init_dict, as these may be needed
|
||||||
# by param descriptions also in _init_dict
|
# by param descriptions also in _init_dict
|
||||||
|
@ -359,9 +374,7 @@ class MetaConfigNode(type):
|
||||||
for key,val in cls._init_dict.items():
|
for key,val in cls._init_dict.items():
|
||||||
# param descriptions
|
# param descriptions
|
||||||
if isinstance(val, _Param):
|
if isinstance(val, _Param):
|
||||||
cls._params[key] = val
|
cls._new_param(key, val)
|
||||||
# try to resolve local param types in local param_types scope
|
|
||||||
val.maybe_resolve_type(cls._param_types)
|
|
||||||
|
|
||||||
# init-time-only keywords
|
# init-time-only keywords
|
||||||
elif cls.init_keywords.has_key(key):
|
elif cls.init_keywords.has_key(key):
|
||||||
|
@ -384,99 +397,6 @@ class MetaConfigNode(type):
|
||||||
else:
|
else:
|
||||||
setattr(cls, key, val)
|
setattr(cls, key, val)
|
||||||
|
|
||||||
|
|
||||||
def _isvalue(cls, name):
|
|
||||||
for c in cls._bases:
|
|
||||||
if c._params.has_key(name):
|
|
||||||
return True
|
|
||||||
|
|
||||||
for c in cls._bases:
|
|
||||||
if c._values.has_key(name):
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
# generator that iterates across all parameters for this class and
|
|
||||||
# all classes it inherits from
|
|
||||||
def _getparams(cls):
|
|
||||||
params = {}
|
|
||||||
for c in cls._bases:
|
|
||||||
for p,v in c._params.iteritems():
|
|
||||||
if not params.has_key(p):
|
|
||||||
params[p] = v
|
|
||||||
return params
|
|
||||||
|
|
||||||
# Lookup a parameter description by name in the given class.
|
|
||||||
def _getparam(cls, name, default = AttributeError):
|
|
||||||
for c in cls._bases:
|
|
||||||
if c._params.has_key(name):
|
|
||||||
return c._params[name]
|
|
||||||
if isSubClass(default, Exception):
|
|
||||||
raise default, \
|
|
||||||
"object '%s' has no attribute '%s'" % (cls.__name__, name)
|
|
||||||
else:
|
|
||||||
return default
|
|
||||||
|
|
||||||
def _hasvalue(cls, name):
|
|
||||||
for c in cls._bases:
|
|
||||||
if c._values.has_key(name):
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _getvalues(cls):
|
|
||||||
values = {}
|
|
||||||
for i,c in enumerate(cls._bases):
|
|
||||||
for p,v in c._values.iteritems():
|
|
||||||
if not values.has_key(p):
|
|
||||||
values[p] = v
|
|
||||||
for p,v in c._params.iteritems():
|
|
||||||
if not values.has_key(p) and hasattr(v, 'default'):
|
|
||||||
try:
|
|
||||||
v.valid(v.default)
|
|
||||||
except TypeError:
|
|
||||||
panic("Invalid default %s for param %s in node %s"
|
|
||||||
% (v.default,p,cls.__name__))
|
|
||||||
v = v.default
|
|
||||||
cls._setvalue(p, v)
|
|
||||||
values[p] = v
|
|
||||||
|
|
||||||
return values
|
|
||||||
|
|
||||||
def _getvalue(cls, name, default = AttributeError):
|
|
||||||
value = None
|
|
||||||
for c in cls._bases:
|
|
||||||
if c._values.has_key(name):
|
|
||||||
value = c._values[name]
|
|
||||||
break
|
|
||||||
if value is not None:
|
|
||||||
return value
|
|
||||||
|
|
||||||
param = cls._getparam(name, None)
|
|
||||||
if param is not None and hasattr(param, 'default'):
|
|
||||||
param.valid(param.default)
|
|
||||||
value = param.default
|
|
||||||
cls._setvalue(name, value)
|
|
||||||
return value
|
|
||||||
|
|
||||||
if isSubClass(default, Exception):
|
|
||||||
raise default, 'value for %s not found' % name
|
|
||||||
else:
|
|
||||||
return default
|
|
||||||
|
|
||||||
def _setvalue(cls, name, value):
|
|
||||||
cls._values[name] = value
|
|
||||||
|
|
||||||
def __getattr__(cls, attr):
|
|
||||||
if cls._isvalue(attr):
|
|
||||||
return Value(cls, attr)
|
|
||||||
|
|
||||||
if attr == '_cpp_param_decl' and hasattr(cls, 'type'):
|
|
||||||
return cls.type + '*'
|
|
||||||
|
|
||||||
raise AttributeError, \
|
|
||||||
"object '%s' has no attribute '%s'" % (cls.__name__, attr)
|
|
||||||
|
|
||||||
def _set_keyword(cls, keyword, val, kwtype):
|
def _set_keyword(cls, keyword, val, kwtype):
|
||||||
if not isinstance(val, kwtype):
|
if not isinstance(val, kwtype):
|
||||||
raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \
|
raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \
|
||||||
|
@ -485,6 +405,13 @@ class MetaConfigNode(type):
|
||||||
val = classmethod(val)
|
val = classmethod(val)
|
||||||
type.__setattr__(cls, keyword, val)
|
type.__setattr__(cls, keyword, val)
|
||||||
|
|
||||||
|
def _new_param(cls, name, value):
|
||||||
|
cls._params[name] = value
|
||||||
|
if hasattr(value, 'default'):
|
||||||
|
cls._values[name] = value.default
|
||||||
|
# try to resolve local param types in local param_types scope
|
||||||
|
value.maybe_resolve_type(cls._param_types)
|
||||||
|
|
||||||
# Set attribute (called on foo.attr = value when foo is an
|
# Set attribute (called on foo.attr = value when foo is an
|
||||||
# instance of class cls).
|
# instance of class cls).
|
||||||
def __setattr__(cls, attr, value):
|
def __setattr__(cls, attr, value):
|
||||||
|
@ -498,23 +425,33 @@ class MetaConfigNode(type):
|
||||||
return
|
return
|
||||||
|
|
||||||
# must be SimObject param
|
# must be SimObject param
|
||||||
param = cls._getparam(attr, None)
|
param = cls._params.get(attr, None)
|
||||||
if param:
|
if param:
|
||||||
# It's ok: set attribute by delegating to 'object' class.
|
# It's ok: set attribute by delegating to 'object' class.
|
||||||
# Note the use of param.make_value() to verify/canonicalize
|
# Note the use of param.make_value() to verify/canonicalize
|
||||||
# the assigned value
|
# the assigned value
|
||||||
try:
|
try:
|
||||||
param.valid(value)
|
param.valid(value)
|
||||||
except:
|
except Exception, e:
|
||||||
panic("Error setting param %s.%s to %s\n" % \
|
panic("Exception: %s\nError setting param %s.%s to %s\n" % \
|
||||||
(cls.__name__, attr, value))
|
(e, cls.__name__, attr, value))
|
||||||
cls._setvalue(attr, value)
|
cls._values[attr] = value
|
||||||
elif isConfigNode(value) or isSimObjSequence(value):
|
elif isConfigNode(value) or isSimObjSequence(value):
|
||||||
cls._setvalue(attr, value)
|
cls._values[attr] = value
|
||||||
else:
|
else:
|
||||||
raise AttributeError, \
|
raise AttributeError, \
|
||||||
"Class %s has no parameter %s" % (cls.__name__, attr)
|
"Class %s has no parameter %s" % (cls.__name__, attr)
|
||||||
|
|
||||||
|
def __getattr__(cls, attr):
|
||||||
|
if cls._params.has_key(attr) or cls._values.has_key(attr):
|
||||||
|
return Value(cls, attr)
|
||||||
|
|
||||||
|
if attr == '_cpp_param_decl' and hasattr(cls, 'type'):
|
||||||
|
return cls.type + '*'
|
||||||
|
|
||||||
|
raise AttributeError, \
|
||||||
|
"object '%s' has no attribute '%s'" % (cls.__name__, attr)
|
||||||
|
|
||||||
def add_child(cls, instance, name, child):
|
def add_child(cls, instance, name, child):
|
||||||
if isNullPointer(child) or instance.top_child_names.has_key(name):
|
if isNullPointer(child) or instance.top_child_names.has_key(name):
|
||||||
return
|
return
|
||||||
|
@ -544,7 +481,7 @@ class MetaConfigNode(type):
|
||||||
if hasattr(cls, 'check'):
|
if hasattr(cls, 'check'):
|
||||||
cls.check()
|
cls.check()
|
||||||
|
|
||||||
for key,value in cls._getvalues().iteritems():
|
for key,value in cls._values.iteritems():
|
||||||
if isConfigNode(value):
|
if isConfigNode(value):
|
||||||
cls.add_child(instance, key, value)
|
cls.add_child(instance, key, value)
|
||||||
if isinstance(value, (list, tuple)):
|
if isinstance(value, (list, tuple)):
|
||||||
|
@ -552,11 +489,10 @@ class MetaConfigNode(type):
|
||||||
if len(vals):
|
if len(vals):
|
||||||
cls.add_child(instance, key, vals)
|
cls.add_child(instance, key, vals)
|
||||||
|
|
||||||
for pname,param in cls._getparams().iteritems():
|
for pname,param in cls._params.iteritems():
|
||||||
try:
|
value = cls._values.get(pname, None)
|
||||||
value = cls._getvalue(pname)
|
if value is None:
|
||||||
except:
|
panic('Error getting %s from %s' % (pname, name))
|
||||||
panic('Error getting %s' % pname)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if isConfigNode(value):
|
if isConfigNode(value):
|
||||||
|
@ -573,10 +509,9 @@ class MetaConfigNode(type):
|
||||||
p = NodeParam(pname, param, value)
|
p = NodeParam(pname, param, value)
|
||||||
instance.params.append(p)
|
instance.params.append(p)
|
||||||
instance.param_names[pname] = p
|
instance.param_names[pname] = p
|
||||||
except:
|
except Exception, e:
|
||||||
print 'Exception while evaluating %s.%s' % \
|
raise e.__class__, 'Exception while evaluating %s.%s\n%s' % \
|
||||||
(instance.path, pname)
|
(instance.path, pname, e)
|
||||||
raise
|
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
@ -615,7 +550,7 @@ class ConfigNode(object):
|
||||||
cls._anon_subclass_counter += 1
|
cls._anon_subclass_counter += 1
|
||||||
return cls.__metaclass__(name, (cls, ), kwargs)
|
return cls.__metaclass__(name, (cls, ), kwargs)
|
||||||
|
|
||||||
class ParamContext(ConfigNode):
|
class ParamContext(ConfigNode,ParamType):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class MetaSimObject(MetaConfigNode):
|
class MetaSimObject(MetaConfigNode):
|
||||||
|
@ -757,9 +692,9 @@ class Node(object):
|
||||||
param.value = [ self.unproxy(pv, ptype) for pv in pval ]
|
param.value = [ self.unproxy(pv, ptype) for pv in pval ]
|
||||||
else:
|
else:
|
||||||
param.value = self.unproxy(pval, ptype)
|
param.value = self.unproxy(pval, ptype)
|
||||||
except:
|
except Exception, e:
|
||||||
print 'Error while fixing up %s:%s' % (self.path, param.name)
|
raise e.__class__, 'Error while fixing up %s:%s\n%s' % \
|
||||||
raise
|
(self.path, param.name, e)
|
||||||
|
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
assert(child != self)
|
assert(child != self)
|
||||||
|
@ -778,9 +713,8 @@ class Node(object):
|
||||||
# before cpu0). Changing ordering can also influence timing
|
# before cpu0). Changing ordering can also influence timing
|
||||||
# in the current memory system, as caches get added to a bus
|
# in the current memory system, as caches get added to a bus
|
||||||
# in different orders which affects their priority in the
|
# in different orders which affects their priority in the
|
||||||
# case of simulataneous requests. We should uncomment the
|
# case of simulataneous requests.
|
||||||
# following line once we take care of that issue.
|
self.children.sort(lambda x,y: cmp(x.name, y.name))
|
||||||
# self.children.sort(lambda x,y: cmp(x.name, y.name))
|
|
||||||
children = [ c.name for c in self.children if not c.paramcontext]
|
children = [ c.name for c in self.children if not c.paramcontext]
|
||||||
print 'children =', ' '.join(children)
|
print 'children =', ' '.join(children)
|
||||||
|
|
||||||
|
@ -792,9 +726,9 @@ class Node(object):
|
||||||
|
|
||||||
value = param.convert(param.value)
|
value = param.convert(param.value)
|
||||||
string = param.string(value)
|
string = param.string(value)
|
||||||
except:
|
except Exception, e:
|
||||||
print 'exception in %s:%s' % (self.path, param.name)
|
raise e.__class__, 'exception in %s:%s\n%s' % \
|
||||||
raise
|
(self.path, param.name, e)
|
||||||
|
|
||||||
print '%s = %s' % (param.name, string)
|
print '%s = %s' % (param.name, string)
|
||||||
|
|
||||||
|
@ -827,8 +761,9 @@ class Node(object):
|
||||||
|
|
||||||
value = param.convert(param.value)
|
value = param.convert(param.value)
|
||||||
string = param.string(value)
|
string = param.string(value)
|
||||||
except:
|
except Exception, e:
|
||||||
print 'exception in %s:%s' % (self.name, param.name)
|
raise e.__class__, 'exception in %s:%s\n%s' % \
|
||||||
|
(self.name, param.name, e)
|
||||||
raise
|
raise
|
||||||
if isConfigNode(param.ptype) and string != "Null":
|
if isConfigNode(param.ptype) and string != "Null":
|
||||||
simobjs.append(string)
|
simobjs.append(string)
|
||||||
|
@ -837,7 +772,8 @@ class Node(object):
|
||||||
|
|
||||||
for so in simobjs:
|
for so in simobjs:
|
||||||
label += "|<%s> %s" % (so, so)
|
label += "|<%s> %s" % (so, so)
|
||||||
dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so, tailport="w"))
|
dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so,
|
||||||
|
tailport="w"))
|
||||||
label += '}'
|
label += '}'
|
||||||
dot.add_node(pydot.Node(self.path,shape="Mrecord",label=label))
|
dot.add_node(pydot.Node(self.path,shape="Mrecord",label=label))
|
||||||
|
|
||||||
|
@ -877,7 +813,7 @@ class Value(object):
|
||||||
super(Value, self).__setattr__('obj', obj)
|
super(Value, self).__setattr__('obj', obj)
|
||||||
|
|
||||||
def _getattr(self):
|
def _getattr(self):
|
||||||
return self.obj._getvalue(self.attr)
|
return self.obj._values.get(self.attr)
|
||||||
|
|
||||||
def __setattr__(self, attr, value):
|
def __setattr__(self, attr, value):
|
||||||
setattr(self._getattr(), attr, value)
|
setattr(self._getattr(), attr, value)
|
||||||
|
|
|
@ -22,7 +22,7 @@ pebi = tebi * 1024
|
||||||
exbi = pebi * 1024
|
exbi = pebi * 1024
|
||||||
|
|
||||||
# memory size configuration stuff
|
# memory size configuration stuff
|
||||||
def to_integer(value):
|
def toInteger(value):
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
result = int(value)
|
result = int(value)
|
||||||
elif value.endswith('Ei'):
|
elif value.endswith('Ei'):
|
||||||
|
@ -64,7 +64,7 @@ def to_integer(value):
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def to_bool(val):
|
def toBool(val):
|
||||||
t = type(val)
|
t = type(val)
|
||||||
if t == bool:
|
if t == bool:
|
||||||
return val
|
return val
|
||||||
|
@ -82,9 +82,9 @@ def to_bool(val):
|
||||||
elif val == "false" or val == "f" or val == "no" or val == "n":
|
elif val == "false" or val == "f" or val == "no" or val == "n":
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return to_integer(val) != 0
|
return toInteger(val) != 0
|
||||||
|
|
||||||
def to_frequency(value):
|
def toFrequency(value):
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
result = float(value)
|
result = float(value)
|
||||||
elif value.endswith('THz'):
|
elif value.endswith('THz'):
|
||||||
|
@ -102,7 +102,7 @@ def to_frequency(value):
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def to_latency(value):
|
def toLatency(value):
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
result = float(value)
|
result = float(value)
|
||||||
elif value.endswith('c'):
|
elif value.endswith('c'):
|
||||||
|
@ -122,7 +122,7 @@ def to_latency(value):
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
def to_network_bandwidth(value):
|
def toNetworkBandwidth(value):
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
result = float(value)
|
result = float(value)
|
||||||
elif value.endswith('Tbps'):
|
elif value.endswith('Tbps'):
|
||||||
|
@ -140,7 +140,7 @@ def to_network_bandwidth(value):
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def to_memory_bandwidth(value):
|
def toMemoryBandwidth(value):
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
result = int(value)
|
result = int(value)
|
||||||
elif value.endswith('PB/s'):
|
elif value.endswith('PB/s'):
|
||||||
|
@ -160,7 +160,7 @@ def to_memory_bandwidth(value):
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def to_memory_size(value):
|
def toMemorySize(value):
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
result = int(value)
|
result = int(value)
|
||||||
elif value.endswith('PB'):
|
elif value.endswith('PB'):
|
||||||
|
|
158
python/m5/multidict.py
Normal file
158
python/m5/multidict.py
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
__all__ = [ 'multidict' ]
|
||||||
|
|
||||||
|
class multidict(object):
|
||||||
|
__nodefault = object()
|
||||||
|
def __init__(self, parent = {}, **kwargs):
|
||||||
|
self.dict = dict(**kwargs)
|
||||||
|
self.parent = parent
|
||||||
|
self.deleted = {}
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(dict(self.items()))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return `dict(self.items())`
|
||||||
|
|
||||||
|
def __contains__(self, key):
|
||||||
|
return self.dict.has_key(key) or self.parent.has_key(key)
|
||||||
|
|
||||||
|
def __delitem__(self, key):
|
||||||
|
try:
|
||||||
|
del self.dict[key]
|
||||||
|
except KeyError, e:
|
||||||
|
if key in self.parent:
|
||||||
|
self.deleted[key] = True
|
||||||
|
else:
|
||||||
|
raise KeyError, e
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
self.deleted.pop(key, False)
|
||||||
|
self.dict[key] = value
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
try:
|
||||||
|
return self.dict[key]
|
||||||
|
except KeyError, e:
|
||||||
|
if not self.deleted.get(key, False) and key in self.parent:
|
||||||
|
return self.parent[key]
|
||||||
|
else:
|
||||||
|
raise KeyError, e
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.dict) + len(self.parent)
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
for key,value in self.dict.items():
|
||||||
|
yield key,value
|
||||||
|
|
||||||
|
if self.parent:
|
||||||
|
for key,value in self.parent.next():
|
||||||
|
if key not in self.dict and key not in self.deleted:
|
||||||
|
yield key,value
|
||||||
|
|
||||||
|
def has_key(self, key):
|
||||||
|
return key in self
|
||||||
|
|
||||||
|
def iteritems(self):
|
||||||
|
for item in self.next():
|
||||||
|
yield item
|
||||||
|
|
||||||
|
def items(self):
|
||||||
|
return [ item for item in self.next() ]
|
||||||
|
|
||||||
|
def iterkeys(self):
|
||||||
|
for key,value in self.next():
|
||||||
|
yield key
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
return [ key for key,value in self.next() ]
|
||||||
|
|
||||||
|
def itervalues(self):
|
||||||
|
for key,value in self.next():
|
||||||
|
yield value
|
||||||
|
|
||||||
|
def values(self):
|
||||||
|
return [ value for key,value in self.next() ]
|
||||||
|
|
||||||
|
def get(self, key, default=__nodefault):
|
||||||
|
try:
|
||||||
|
return self[key]
|
||||||
|
except KeyError, e:
|
||||||
|
if default != self.__nodefault:
|
||||||
|
return default
|
||||||
|
else:
|
||||||
|
raise KeyError, e
|
||||||
|
|
||||||
|
def setdefault(self, key, default):
|
||||||
|
try:
|
||||||
|
return self[key]
|
||||||
|
except KeyError:
|
||||||
|
self.deleted.pop(key, False)
|
||||||
|
self.dict[key] = default
|
||||||
|
return default
|
||||||
|
|
||||||
|
def _dump(self):
|
||||||
|
print 'multidict dump'
|
||||||
|
node = self
|
||||||
|
while isinstance(node, multidict):
|
||||||
|
print ' ', node.dict
|
||||||
|
node = node.parent
|
||||||
|
|
||||||
|
def _dumpkey(self, key):
|
||||||
|
values = []
|
||||||
|
node = self
|
||||||
|
while isinstance(node, multidict):
|
||||||
|
if key in node.dict:
|
||||||
|
values.append(node.dict[key])
|
||||||
|
node = node.parent
|
||||||
|
print key, values
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test1 = multidict()
|
||||||
|
test2 = multidict(test1)
|
||||||
|
test3 = multidict(test2)
|
||||||
|
test4 = multidict(test3)
|
||||||
|
|
||||||
|
test1['a'] = 'test1_a'
|
||||||
|
test1['b'] = 'test1_b'
|
||||||
|
test1['c'] = 'test1_c'
|
||||||
|
test1['d'] = 'test1_d'
|
||||||
|
test1['e'] = 'test1_e'
|
||||||
|
|
||||||
|
test2['a'] = 'test2_a'
|
||||||
|
del test2['b']
|
||||||
|
test2['c'] = 'test2_c'
|
||||||
|
del test1['a']
|
||||||
|
|
||||||
|
test2.setdefault('f', multidict)
|
||||||
|
|
||||||
|
print 'test1>', test1.items()
|
||||||
|
print 'test2>', test2.items()
|
||||||
|
#print test1['a']
|
||||||
|
print test1['b']
|
||||||
|
print test1['c']
|
||||||
|
print test1['d']
|
||||||
|
print test1['e']
|
||||||
|
|
||||||
|
print test2['a']
|
||||||
|
#print test2['b']
|
||||||
|
print test2['c']
|
||||||
|
print test2['d']
|
||||||
|
print test2['e']
|
||||||
|
|
||||||
|
for key in test2.iterkeys():
|
||||||
|
print key
|
||||||
|
|
||||||
|
test2.get('g', 'foo')
|
||||||
|
#test2.get('b')
|
||||||
|
test2.get('b', 'bar')
|
||||||
|
test2.setdefault('b', 'blah')
|
||||||
|
print test1
|
||||||
|
print test2
|
||||||
|
print `test2`
|
||||||
|
|
||||||
|
print len(test2)
|
||||||
|
|
||||||
|
test3['a'] = [ 0, 1, 2, 3 ]
|
||||||
|
|
||||||
|
print test4
|
|
@ -20,13 +20,13 @@ class SmartDict(dict):
|
||||||
|
|
||||||
class Proxy(str):
|
class Proxy(str):
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
return int(to_integer(str(self)))
|
return int(toInteger(str(self)))
|
||||||
def __long__(self):
|
def __long__(self):
|
||||||
return long(to_integer(str(self)))
|
return long(toInteger(str(self)))
|
||||||
def __float__(self):
|
def __float__(self):
|
||||||
return float(to_integer(str(self)))
|
return float(toInteger(str(self)))
|
||||||
def __nonzero__(self):
|
def __nonzero__(self):
|
||||||
return to_bool(str(self))
|
return toBool(str(self))
|
||||||
def convert(self, other):
|
def convert(self, other):
|
||||||
t = type(other)
|
t = type(other)
|
||||||
if t == bool:
|
if t == bool:
|
||||||
|
|
Loading…
Reference in a new issue