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:
4 # 1) Undefined variables should return False rather than raising KeyError.
6 # 2) String values of 'False', '0', etc., should evaluate to False
7 # (not just the empty string).
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
19 class SmartDict(dict):
23 return int(to_integer(str(self
)))
25 return long(to_integer(str(self
)))
27 return float(to_integer(str(self
)))
28 def __nonzero__(self
):
29 return to_bool(str(self
))
30 def convert(self
, other
):
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
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
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
)
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
83 def __getitem__(self
, key
):
84 return self
.Proxy(dict.get(self
, key
, 'False'))
86 def __setitem__(self
, key
, item
):
87 dict.__setitem
__(self
, key
, str(item
))
90 return [ self
.Proxy(v
) for v
in dict.values(self
) ]
93 for value
in dict.itervalues(self
):
94 yield self
.Proxy(value
)
97 return [ (k
, self
.Proxy(v
)) for k
,v
in dict.items(self
) ]
100 for key
,value
in dict.iteritems(self
):
101 yield key
, self
.Proxy(value
)
103 def get(self
, key
, default
='False'):
104 return self
.Proxy(dict.get(self
, key
, str(default
)))
106 def setdefault(self
, key
, default
='False'):
107 return self
.Proxy(dict.setdefault(self
, key
, str(default
)))