smartdict.py revision 1530
16691Stjones1@inf.ed.ac.uk# The SmartDict class fixes a couple of issues with using the content
26691Stjones1@inf.ed.ac.uk# of os.environ or similar dicts of strings as Python variables:
36691Stjones1@inf.ed.ac.uk#
46691Stjones1@inf.ed.ac.uk# 1) Undefined variables should return False rather than raising KeyError.
56691Stjones1@inf.ed.ac.uk#
66691Stjones1@inf.ed.ac.uk# 2) String values of 'False', '0', etc., should evaluate to False
76691Stjones1@inf.ed.ac.uk#    (not just the empty string).
86691Stjones1@inf.ed.ac.uk#
96691Stjones1@inf.ed.ac.uk# #1 is solved by overriding __getitem__, and #2 is solved by using a
106691Stjones1@inf.ed.ac.uk# proxy class for values and overriding __nonzero__ on the proxy.
116691Stjones1@inf.ed.ac.uk# Everything else is just to (a) make proxies behave like normal
126691Stjones1@inf.ed.ac.uk# values otherwise, (b) make sure any dict operation returns a proxy
136691Stjones1@inf.ed.ac.uk# rather than a normal value, and (c) coerce values written to the
146691Stjones1@inf.ed.ac.uk# dict to be strings.
156691Stjones1@inf.ed.ac.uk
166691Stjones1@inf.ed.ac.uk
176691Stjones1@inf.ed.ac.ukfrom convert import *
186691Stjones1@inf.ed.ac.uk
196691Stjones1@inf.ed.ac.ukclass SmartDict(dict):
206691Stjones1@inf.ed.ac.uk
216691Stjones1@inf.ed.ac.uk    class Proxy(str):
226691Stjones1@inf.ed.ac.uk        def __int__(self):
236691Stjones1@inf.ed.ac.uk            return int(to_integer(str(self)))
246691Stjones1@inf.ed.ac.uk        def __long__(self):
256691Stjones1@inf.ed.ac.uk            return long(to_integer(str(self)))
266691Stjones1@inf.ed.ac.uk        def __float__(self):
276691Stjones1@inf.ed.ac.uk            return float(to_integer(str(self)))
286691Stjones1@inf.ed.ac.uk        def __nonzero__(self):
296691Stjones1@inf.ed.ac.uk            return to_bool(str(self))
306691Stjones1@inf.ed.ac.uk        def convert(self, other):
316691Stjones1@inf.ed.ac.uk            t = type(other)
326691Stjones1@inf.ed.ac.uk            if t == bool:
3311793Sbrandon.potter@amd.com                return bool(self)
3411793Sbrandon.potter@amd.com            if t == int:
356691Stjones1@inf.ed.ac.uk                return int(self)
366691Stjones1@inf.ed.ac.uk            if t == long:
376691Stjones1@inf.ed.ac.uk                return long(self)
386691Stjones1@inf.ed.ac.uk            if t == float:
3912334Sgabeblack@google.com                return float(self)
406691Stjones1@inf.ed.ac.uk            return str(self)
418232Snate@binkert.org        def __lt__(self, other):
426691Stjones1@inf.ed.ac.uk            return self.convert(other) < other
4312431Sgabeblack@google.com        def __le__(self, other):
4411854Sbrandon.potter@amd.com            return self.convert(other) <= other
456691Stjones1@inf.ed.ac.uk        def __eq__(self, other):
4611800Sbrandon.potter@amd.com            return self.convert(other) == other
476691Stjones1@inf.ed.ac.uk        def __ne__(self, other):
486691Stjones1@inf.ed.ac.uk            return self.convert(other) != other
496691Stjones1@inf.ed.ac.uk        def __gt__(self, other):
506691Stjones1@inf.ed.ac.uk            return self.convert(other) > other
516691Stjones1@inf.ed.ac.uk        def __ge__(self, other):
5211851Sbrandon.potter@amd.com            return self.convert(other) >= other
5312448Sgabeblack@google.com
5412448Sgabeblack@google.com        def __add__(self, other):
5512432Sgabeblack@google.com            return self.convert(other) + other
566691Stjones1@inf.ed.ac.uk        def __sub__(self, other):
5712441Sgabeblack@google.com            return self.convert(other) - other
5811905SBrandon.Potter@amd.com        def __mul__(self, other):
5911905SBrandon.Potter@amd.com            return self.convert(other) * other
6011905SBrandon.Potter@amd.com        def __div__(self, other):
6111905SBrandon.Potter@amd.com            return self.convert(other) / other
6211905SBrandon.Potter@amd.com        def __truediv__(self, other):
6311905SBrandon.Potter@amd.com            return self.convert(other) / other
6411905SBrandon.Potter@amd.com
6511905SBrandon.Potter@amd.com        def __radd__(self, other):
666691Stjones1@inf.ed.ac.uk            return other + self.convert(other)
676691Stjones1@inf.ed.ac.uk        def __rsub__(self, other):
6811905SBrandon.Potter@amd.com            return other - self.convert(other)
696691Stjones1@inf.ed.ac.uk        def __rmul__(self, other):
706691Stjones1@inf.ed.ac.uk            return other * self.convert(other)
7111905SBrandon.Potter@amd.com        def __rdiv__(self, other):
7211905SBrandon.Potter@amd.com            return other / self.convert(other)
7311905SBrandon.Potter@amd.com        def __rtruediv__(self, other):
7411905SBrandon.Potter@amd.com            return other / self.convert(other)
756691Stjones1@inf.ed.ac.uk
766691Stjones1@inf.ed.ac.uk
776691Stjones1@inf.ed.ac.uk    def __getitem__(self, key):
7811851Sbrandon.potter@amd.com        return self.Proxy(dict.get(self, key, 'False'))
796691Stjones1@inf.ed.ac.uk
807532Ssteve.reinhardt@amd.com    def __setitem__(self, key, item):
817532Ssteve.reinhardt@amd.com        dict.__setitem__(self, key, str(item))
8210318Sandreas.hansson@arm.com
836691Stjones1@inf.ed.ac.uk    def values(self):
846691Stjones1@inf.ed.ac.uk        return [ self.Proxy(v) for v in dict.values(self) ]
856691Stjones1@inf.ed.ac.uk
8611851Sbrandon.potter@amd.com    def itervalues(self):
876691Stjones1@inf.ed.ac.uk        for value in dict.itervalues(self):
8813894Sgabeblack@google.com            yield self.Proxy(value)
896691Stjones1@inf.ed.ac.uk
906691Stjones1@inf.ed.ac.uk    def items(self):
916691Stjones1@inf.ed.ac.uk        return [ (k, self.Proxy(v)) for k,v in dict.items(self) ]
926691Stjones1@inf.ed.ac.uk
936691Stjones1@inf.ed.ac.uk    def iteritems(self):
946691Stjones1@inf.ed.ac.uk        for key,value in dict.iteritems(self):
956691Stjones1@inf.ed.ac.uk            yield key, self.Proxy(value)
966691Stjones1@inf.ed.ac.uk
976691Stjones1@inf.ed.ac.uk    def get(self, key, default='False'):
986691Stjones1@inf.ed.ac.uk        return self.Proxy(dict.get(self, key, str(default)))
9911389Sbrandon.potter@amd.com
10011389Sbrandon.potter@amd.com    def setdefault(self, key, default='False'):
10111389Sbrandon.potter@amd.com        return self.Proxy(dict.setdefault(self, key, str(default)))
1026691Stjones1@inf.ed.ac.uk
1036691Stjones1@inf.ed.ac.uk