Package web2py :: Package gluon :: Module storage

[hide private]
[frames] | no frames]

# Source Code for Module web2py.gluon.storage

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3
      4  """
      5  This file is part of the web2py Web Framework
      6  Copyrighted by Massimo Di Pierro <mdipierro@cs.depaul.edu>
      7  License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
      8
      9  Provides:
     10
     11  - List; like list but returns None instead of IndexOutOfBounds
     12  - Storage; like dictionary allowing also for `obj.foo` for `obj['foo']`
     13  """
     14
     15  import cPickle
     16  import portalocker
     17
     18  __all__ = ['List', 'Storage', 'Settings', 'Messages',
     19             'StorageList', 'load_storage', 'save_storage']
     20
     21
     22 -class List(list):
     23      """
     24      Like a regular python list but a[i] if i is out of bounds return None
     25      instead of IndexOutOfBounds
     26      """
     27
     28 -    def __call__(self, i, default=None):
     29          if 0<=i<len(self):
     30              return self[i]
     31          else:
     32              return default
     33
     34 -class Storage(dict):
     35
     36      """
     37      A Storage object is like a dictionary except `obj.foo` can be used
     38      in addition to `obj['foo']`, and setting obj.foo = None deletes item foo.
     39
     40          >>> o = Storage(a=1)
     41          >>> print o.a
     42          1
     43
     44          >>> o['a']
     45          1
     46
     47          >>> o.a = 2
     48          >>> print o['a']
     49          2
     50
     51          >>> del o.a
     52          >>> print o.a
     53          None
     54
     55      """
     56
     57 -    def __getattr__(self, key):
     58          return dict.get(self, key, None)
     59
     60 -    def __setattr__(self, key, value):
     61          if value is None:
     62              if key in self:
     63                  del self[key]
     64          else:
     65              self[key] = value
     66
     67 -    def __delattr__(self, key):
     68          if key in self:
     69              del self[key]
     70          else:
     71              raise AttributeError, "missing key=%s" % key
     72
     73 -    def __getitem__(self, key):
     74          return dict.get(self, key, None)
     75
     76 -    def __repr__(self):
     77          return '<Storage ' + dict.__repr__(self) + '>'
     78
     79 -    def __getstate__(self):
     80          return dict(self)
     81
     82 -    def __setstate__(self, value):
     83          for (k, v) in value.items():
     84              self[k] = v
     85
     86 -    def getlist(self, key):
     87          """Return a Storage value as a list.
     88
     89          If the value is a list it will be returned as-is.
     90          If object is None, an empty list will be returned.
     91          Otherwise, [value] will be returned.
     92
     93          Example output for a query string of ?x=abc&y=abc&y=def
     94          >>> request = Storage()
     95          >>> request.vars = Storage()
     96          >>> request.vars.x = 'abc'
     97          >>> request.vars.y = ['abc', 'def']
     98          >>> request.vars.getlist('x')
     99          ['abc']
    100          >>> request.vars.getlist('y')
    101          ['abc', 'def']
    102          >>> request.vars.getlist('z')
    103          []
    104
    105          """
    106          value = self.get(key, None)
    107          if isinstance(value, (list, tuple)):
    108              return value
    109          elif value is None:
    110              return []
    111          return [value]
    112
    113 -    def getfirst(self, key):
    114          """Return the first or only value when given a request.vars-style key.
    115
    116          If the value is a list, its first item will be returned;
    117          otherwise, the value will be returned as-is.
    118
    119          Example output for a query string of ?x=abc&y=abc&y=def
    120          >>> request = Storage()
    121          >>> request.vars = Storage()
    122          >>> request.vars.x = 'abc'
    123          >>> request.vars.y = ['abc', 'def']
    124          >>> request.vars.getfirst('x')
    125          'abc'
    126          >>> request.vars.getfirst('y')
    127          'abc'
    128          >>> request.vars.getfirst('z')
    129
    130          """
    131          value = self.getlist(key)
    132          if len(value):
    133              return value[0]
    134          return None
    135
    136 -    def getlast(self, key):
    137          """Returns the last or only single value when given a request.vars-style key.
    138
    139          If the value is a list, the last item will be returned;
    140          otherwise, the value will be returned as-is.
    141
    142          Simulated output with a query string of ?x=abc&y=abc&y=def
    143          >>> request = Storage()
    144          >>> request.vars = Storage()
    145          >>> request.vars.x = 'abc'
    146          >>> request.vars.y = ['abc', 'def']
    147          >>> request.vars.getlast('x')
    148          'abc'
    149          >>> request.vars.getlast('y')
    150          'def'
    151          >>> request.vars.getlast('z')
    152
    153          """
    154          value = self.getlist(key)
    155          if len(value):
    156              return value[-1]
    157          return None
    158
    159  PICKABLE = (str,int,long,float,bool,list,dict,tuple,set)
    160 -def PickleableStorage(data):
    161      return Storage(dict((k,v) for (k,v) in data.items() if isinstance(v,PICKABLE)))
    162
    163 -class StorageList(Storage):
    164      """
    165      like Storage but missing elements default to [] instead of None
    166      """
    167 -    def __getattr__(self, key):
    168          if key in self:
    169              return self[key]
    170          else:
    171              self[key] = []
    172              return self[key]
    173
    174 -def load_storage(filename):
    175      fp = None
    176      try:
    177          fp = portalocker.LockedFile(filename, 'rb')
    178          storage = cPickle.load(fp)
    179      finally:
    180          if fp: fp.close()
    181      return Storage(storage)
    182
    183
    184 -def save_storage(storage, filename):
    185      fp = None
    186      try:
    187          fp = portalocker.LockedFile(filename, 'wb')
    188          cPickle.dump(dict(storage), fp)
    189      finally:
    190          if fp: fp.close()
    191
    192 -class Settings(Storage):
    193
    194 -    def __setattr__(self, key, value):
    195          if key != 'lock_keys' and self.get('lock_keys', None)\
    196               and not key in self:
    197              raise SyntaxError, 'setting key \'%s\' does not exist' % key
    198          if key != 'lock_values' and self.get('lock_values', None):
    199              raise SyntaxError, 'setting value cannot be changed: %s' % key
    200          self[key] = value
    201
    202
    203 -class Messages(Storage):
    204
    205 -    def __init__(self, T):
    206          self['T'] = T
    207
    208 -    def __setattr__(self, key, value):
    209          if key != 'lock_keys' and self.get('lock_keys', None)\
    210               and not key in self:
    211              raise SyntaxError, 'setting key \'%s\' does not exist' % key
    212          if key != 'lock_values' and self.get('lock_values', None):
    213              raise SyntaxError, 'setting value cannot be changed: %s' % key
    214          self[key] = value
    215
    216 -    def __getattr__(self, key):
    217          value = self[key]
    218          if isinstance(value, str):
    219              return str(self['T'](value))
    220          return value
    221
    222  if __name__ == '__main__':
    223      import doctest
    224      doctest.testmod()
    225