Add a comment to smartdict.py.
[gem5.git] / python / m5 / smartdict.py
1 # The SmartDict class fixes a couple of issues with using the content
2 # of os.environ or similar dicts of strings as Python variables:
3 #
4 # 1) Undefined variables should return False rather than raising KeyError.
5 #
6 # 2) String values of 'False', '0', etc., should evaluate to False
7 # (not just the empty string).
8 #
9 # #1 is solved by overriding __getitem__, and #2 is solved by using a
10 # proxy class for values and overriding __nonzero__ on the proxy.
11 # Everything else is just to (a) make proxies behave like normal
12 # values otherwise, (b) make sure any dict operation returns a proxy
13 # rather than a normal value, and (c) coerce values written to the
14 # dict to be strings.
15
16
17 from convert import *
18
19 class SmartDict(dict):
20
21 class Proxy(str):
22 def __int__(self):
23 return int(to_integer(str(self)))
24 def __long__(self):
25 return long(to_integer(str(self)))
26 def __float__(self):
27 return float(to_integer(str(self)))
28 def __nonzero__(self):
29 return to_bool(str(self))
30 def convert(self, other):
31 t = type(other)
32 if t == bool:
33 return bool(self)
34 if t == int:
35 return int(self)
36 if t == long:
37 return long(self)
38 if t == float:
39 return float(self)
40 return str(self)
41 def __lt__(self, other):
42 return self.convert(other) < other
43 def __le__(self, other):
44 return self.convert(other) <= other
45 def __eq__(self, other):
46 return self.convert(other) == other
47 def __ne__(self, other):
48 return self.convert(other) != other
49 def __gt__(self, other):
50 return self.convert(other) > other
51 def __ge__(self, other):
52 return self.convert(other) >= other
53
54 def __add__(self, other):
55 return self.convert(other) + other
56 def __sub__(self, other):
57 return self.convert(other) - other
58 def __mul__(self, other):
59 return self.convert(other) * other
60 def __div__(self, other):
61 return self.convert(other) / other
62 def __truediv__(self, other):
63 return self.convert(other) / other
64
65 def __radd__(self, other):
66 return other + self.convert(other)
67 def __rsub__(self, other):
68 return other - self.convert(other)
69 def __rmul__(self, other):
70 return other * self.convert(other)
71 def __rdiv__(self, other):
72 return other / self.convert(other)
73 def __rtruediv__(self, other):
74 return other / self.convert(other)
75
76
77 # __getitem__ uses dict.get() to return 'False' if the key is not
78 # found (rather than raising KeyError). Note that this does *not*
79 # set the key's value to 'False' in the dict, so that even after
80 # we call env['foo'] we still get a meaningful answer from "'foo'
81 # in env" (which calls dict.__contains__, which we do not
82 # override).
83 def __getitem__(self, key):
84 return self.Proxy(dict.get(self, key, 'False'))
85
86 def __setitem__(self, key, item):
87 dict.__setitem__(self, key, str(item))
88
89 def values(self):
90 return [ self.Proxy(v) for v in dict.values(self) ]
91
92 def itervalues(self):
93 for value in dict.itervalues(self):
94 yield self.Proxy(value)
95
96 def items(self):
97 return [ (k, self.Proxy(v)) for k,v in dict.items(self) ]
98
99 def iteritems(self):
100 for key,value in dict.iteritems(self):
101 yield key, self.Proxy(value)
102
103 def get(self, key, default='False'):
104 return self.Proxy(dict.get(self, key, str(default)))
105
106 def setdefault(self, key, default='False'):
107 return self.Proxy(dict.setdefault(self, key, str(default)))
108