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