smartdict.py revision 13714:35636064b7a1
110428Sandreas.hansson@arm.com# Copyright (c) 2005 The Regents of The University of Michigan 210428Sandreas.hansson@arm.com# All rights reserved. 310428Sandreas.hansson@arm.com# 410428Sandreas.hansson@arm.com# Redistribution and use in source and binary forms, with or without 510428Sandreas.hansson@arm.com# modification, are permitted provided that the following conditions are 610428Sandreas.hansson@arm.com# met: redistributions of source code must retain the above copyright 710428Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer; 810428Sandreas.hansson@arm.com# redistributions in binary form must reproduce the above copyright 910428Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer in the 1010428Sandreas.hansson@arm.com# documentation and/or other materials provided with the distribution; 1110428Sandreas.hansson@arm.com# neither the name of the copyright holders nor the names of its 1210428Sandreas.hansson@arm.com# contributors may be used to endorse or promote products derived from 1310428Sandreas.hansson@arm.com# this software without specific prior written permission. 1410428Sandreas.hansson@arm.com# 1510428Sandreas.hansson@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1610428Sandreas.hansson@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1710428Sandreas.hansson@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1810428Sandreas.hansson@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1910428Sandreas.hansson@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2010428Sandreas.hansson@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2110428Sandreas.hansson@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2210428Sandreas.hansson@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2310428Sandreas.hansson@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2410428Sandreas.hansson@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2510428Sandreas.hansson@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2610428Sandreas.hansson@arm.com# 2710428Sandreas.hansson@arm.com# Authors: Nathan Binkert 2810428Sandreas.hansson@arm.com 2910428Sandreas.hansson@arm.com# The SmartDict class fixes a couple of issues with using the content 3010428Sandreas.hansson@arm.com# of os.environ or similar dicts of strings as Python variables: 3110428Sandreas.hansson@arm.com# 3210428Sandreas.hansson@arm.com# 1) Undefined variables should return False rather than raising KeyError. 3310428Sandreas.hansson@arm.com# 3412266Sradhika.jagtap@arm.com# 2) String values of 'False', '0', etc., should evaluate to False 3512266Sradhika.jagtap@arm.com# (not just the empty string). 3612266Sradhika.jagtap@arm.com# 3712266Sradhika.jagtap@arm.com# #1 is solved by overriding __getitem__, and #2 is solved by using a 3812266Sradhika.jagtap@arm.com# proxy class for values and overriding __nonzero__ on the proxy. 3912266Sradhika.jagtap@arm.com# Everything else is just to (a) make proxies behave like normal 4012266Sradhika.jagtap@arm.com# values otherwise, (b) make sure any dict operation returns a proxy 4110428Sandreas.hansson@arm.com# rather than a normal value, and (c) coerce values written to the 4210428Sandreas.hansson@arm.com# dict to be strings. 4310428Sandreas.hansson@arm.com 4410428Sandreas.hansson@arm.comfrom __future__ import print_function 4510428Sandreas.hansson@arm.comfrom __future__ import absolute_import 4610428Sandreas.hansson@arm.com 4710428Sandreas.hansson@arm.comfrom .convert import * 4810428Sandreas.hansson@arm.comfrom .attrdict import attrdict 4910428Sandreas.hansson@arm.com 5010428Sandreas.hansson@arm.comclass Variable(str): 5110428Sandreas.hansson@arm.com """Intelligent proxy class for SmartDict. Variable will use the 5210428Sandreas.hansson@arm.com various convert functions to attempt to convert values to useable 5310428Sandreas.hansson@arm.com types""" 5411555Sjungma@eit.uni-kl.de def __int__(self): 5510428Sandreas.hansson@arm.com return toInteger(str(self)) 5611555Sjungma@eit.uni-kl.de def __long__(self): 5711555Sjungma@eit.uni-kl.de return toLong(str(self)) 5811555Sjungma@eit.uni-kl.de def __float__(self): 5911555Sjungma@eit.uni-kl.de return toFloat(str(self)) 6011555Sjungma@eit.uni-kl.de def __bool__(self): 6110428Sandreas.hansson@arm.com return toBool(str(self)) 6210428Sandreas.hansson@arm.com # Python 2.7 uses __nonzero__ instead of __bool__ 6312266Sradhika.jagtap@arm.com __nonzero__ = __bool__ 6412266Sradhika.jagtap@arm.com def convert(self, other): 6512266Sradhika.jagtap@arm.com t = type(other) 6610428Sandreas.hansson@arm.com if t == bool: 6712266Sradhika.jagtap@arm.com return bool(self) 6810428Sandreas.hansson@arm.com if t == int: 6912266Sradhika.jagtap@arm.com return int(self) 7012266Sradhika.jagtap@arm.com if t == long: 7112266Sradhika.jagtap@arm.com return long(self) 7212266Sradhika.jagtap@arm.com if t == float: 7312266Sradhika.jagtap@arm.com return float(self) 7412266Sradhika.jagtap@arm.com return str(self) 7512266Sradhika.jagtap@arm.com def __lt__(self, other): 7612266Sradhika.jagtap@arm.com return self.convert(other) < other 7712266Sradhika.jagtap@arm.com def __le__(self, other): 7811555Sjungma@eit.uni-kl.de return self.convert(other) <= other 7911555Sjungma@eit.uni-kl.de def __eq__(self, other): 8011555Sjungma@eit.uni-kl.de return self.convert(other) == other 8112266Sradhika.jagtap@arm.com def __ne__(self, other): 8212266Sradhika.jagtap@arm.com return self.convert(other) != other 8312266Sradhika.jagtap@arm.com def __gt__(self, other): 8411555Sjungma@eit.uni-kl.de return self.convert(other) > other 8511555Sjungma@eit.uni-kl.de def __ge__(self, other): 8611555Sjungma@eit.uni-kl.de return self.convert(other) >= other 8712266Sradhika.jagtap@arm.com 8812266Sradhika.jagtap@arm.com def __add__(self, other): 8911555Sjungma@eit.uni-kl.de return self.convert(other) + other 9011555Sjungma@eit.uni-kl.de def __sub__(self, other): 9111555Sjungma@eit.uni-kl.de return self.convert(other) - other 9211555Sjungma@eit.uni-kl.de def __mul__(self, other): 9311555Sjungma@eit.uni-kl.de return self.convert(other) * other 9412266Sradhika.jagtap@arm.com def __div__(self, other): 9512266Sradhika.jagtap@arm.com return self.convert(other) / other 9612266Sradhika.jagtap@arm.com def __truediv__(self, other): 9712266Sradhika.jagtap@arm.com return self.convert(other) / other 9812266Sradhika.jagtap@arm.com 9910428Sandreas.hansson@arm.com def __radd__(self, other): 10010428Sandreas.hansson@arm.com return other + self.convert(other) 10110428Sandreas.hansson@arm.com def __rsub__(self, other): 10210428Sandreas.hansson@arm.com return other - self.convert(other) 10310428Sandreas.hansson@arm.com def __rmul__(self, other): 10410428Sandreas.hansson@arm.com return other * self.convert(other) 10510428Sandreas.hansson@arm.com def __rdiv__(self, other): 10610428Sandreas.hansson@arm.com return other / self.convert(other) 10710428Sandreas.hansson@arm.com def __rtruediv__(self, other): 10810428Sandreas.hansson@arm.com return other / self.convert(other) 10910428Sandreas.hansson@arm.com 11010428Sandreas.hansson@arm.comclass UndefinedVariable(object): 11110428Sandreas.hansson@arm.com """Placeholder class to represent undefined variables. Will 11210428Sandreas.hansson@arm.com generally cause an exception whenever it is used, but evaluates to 11310428Sandreas.hansson@arm.com zero for boolean truth testing such as in an if statement""" 11410428Sandreas.hansson@arm.com def __bool__(self): 11510428Sandreas.hansson@arm.com return False 11610428Sandreas.hansson@arm.com 11710428Sandreas.hansson@arm.com # Python 2.7 uses __nonzero__ instead of __bool__ 11810428Sandreas.hansson@arm.com __nonzero__ = __bool__ 11910428Sandreas.hansson@arm.com 12010428Sandreas.hansson@arm.comclass SmartDict(attrdict): 12110428Sandreas.hansson@arm.com """Dictionary class that holds strings, but intelligently converts 12210428Sandreas.hansson@arm.com those strings to other types depending on their usage""" 12310428Sandreas.hansson@arm.com 12411555Sjungma@eit.uni-kl.de def __getitem__(self, key): 12511555Sjungma@eit.uni-kl.de """returns a Variable proxy if the values exists in the database and 12612266Sradhika.jagtap@arm.com returns an UndefinedVariable otherwise""" 12711555Sjungma@eit.uni-kl.de 12812266Sradhika.jagtap@arm.com if key in self: 12911555Sjungma@eit.uni-kl.de return Variable(dict.get(self, key)) 13012266Sradhika.jagtap@arm.com else: 13112266Sradhika.jagtap@arm.com # Note that this does *not* change the contents of the dict, 13211555Sjungma@eit.uni-kl.de # so that even after we call env['foo'] we still get a 13311555Sjungma@eit.uni-kl.de # meaningful answer from "'foo' in env" (which 13411555Sjungma@eit.uni-kl.de # calls dict.__contains__, which we do not override). 13511555Sjungma@eit.uni-kl.de return UndefinedVariable() 13610428Sandreas.hansson@arm.com 13710428Sandreas.hansson@arm.com def __setitem__(self, key, item): 13810428Sandreas.hansson@arm.com """intercept the setting of any variable so that we always 13911555Sjungma@eit.uni-kl.de store strings in the dict""" 14012266Sradhika.jagtap@arm.com dict.__setitem__(self, key, str(item)) 14112266Sradhika.jagtap@arm.com 14212266Sradhika.jagtap@arm.com def values(self): 14312266Sradhika.jagtap@arm.com for value in dict.values(self): 14412266Sradhika.jagtap@arm.com yield Variable(value) 14512266Sradhika.jagtap@arm.com 14611555Sjungma@eit.uni-kl.de def items(self): 14712266Sradhika.jagtap@arm.com for key,value in dict.items(self): 14812266Sradhika.jagtap@arm.com yield key, Variable(value) 14912266Sradhika.jagtap@arm.com 15012266Sradhika.jagtap@arm.com def get(self, key, default='False'): 15112266Sradhika.jagtap@arm.com return Variable(dict.get(self, key, str(default))) 15212266Sradhika.jagtap@arm.com 15311555Sjungma@eit.uni-kl.de def setdefault(self, key, default='False'): 15410428Sandreas.hansson@arm.com return Variable(dict.setdefault(self, key, str(default))) 15510428Sandreas.hansson@arm.com 15610428Sandreas.hansson@arm.com__all__ = [ 'SmartDict' ] 15710428Sandreas.hansson@arm.com