another attempt at new Storage, thanks Jonathan

This commit is contained in:
mdipierro
2012-08-21 14:30:02 -05:00
parent c6c417af72
commit 61a1fb1d58
5 changed files with 73 additions and 91 deletions
+1 -1
View File
@@ -1 +1 @@
Version 2.00.0 (2012-08-21 13:38:21) dev Version 2.00.0 (2012-08-21 14:29:57) dev
+3 -1
View File
@@ -83,6 +83,7 @@ class Request(Storage):
""" """
def __init__(self): def __init__(self):
Storage.__init__(self)
self.wsgi = Storage() # hooks to environ and start_response self.wsgi = Storage() # hooks to environ and start_response
self.env = Storage() self.env = Storage()
self.cookies = Cookie.SimpleCookie() self.cookies = Cookie.SimpleCookie()
@@ -100,7 +101,7 @@ class Request(Storage):
self.is_https = False self.is_https = False
self.is_local = False self.is_local = False
self.global_settings = settings.global_settings self.global_settings = settings.global_settings
def compute_uuid(self): def compute_uuid(self):
self.uuid = '%s/%s.%s.%s' % ( self.uuid = '%s/%s.%s.%s' % (
self.application, self.application,
@@ -165,6 +166,7 @@ class Response(Storage):
""" """
def __init__(self): def __init__(self):
Storage.__init__(self)
self.status = 200 self.status = 200
self.headers = dict() self.headers = dict()
self.headers['X-Powered-By'] = 'web2py' self.headers['X-Powered-By'] = 'web2py'
+3 -2
View File
@@ -446,8 +446,9 @@ def wsgibase(environ, responder):
elif not request.is_local and \ elif not request.is_local and \
os.path.exists(os.path.join(request.folder,'DISABLED')): os.path.exists(os.path.join(request.folder,'DISABLED')):
raise HTTP(503, "<html><body><h1>Temporarily down for maintenance</h1></body></html>") raise HTTP(503, "<html><body><h1>Temporarily down for maintenance</h1></body></html>")
request.url = Url(r=request, args=request.args, request.url = Url(r=request,
extension=request.raw_extension) args=request.args,
extension=request.raw_extension)
# ################################################## # ##################################################
# build missing folders # build missing folders
+1
View File
@@ -33,6 +33,7 @@ class TicketStorage(Storage):
db=None, db=None,
tablename='web2py_ticket' tablename='web2py_ticket'
): ):
Storage.__init__(self)
self.db = db self.db = db
self.tablename = tablename self.tablename = tablename
+65 -87
View File
@@ -13,9 +13,8 @@ Provides:
""" """
import cPickle import cPickle
import portalocker
__all__ = ['List', 'Storage', 'Settings', 'Messages', 'PickleableStorage', __all__ = ['List', 'Storage', 'Settings', 'Messages',
'StorageList', 'load_storage', 'save_storage'] 'StorageList', 'load_storage', 'save_storage']
@@ -25,7 +24,11 @@ class List(list):
instead of IndexOutOfBounds instead of IndexOutOfBounds
""" """
def __call__(self, i, default=None, cast=None, url_onerror=None): def __call__(self, i, default=None, cast=None, otherwise=None):
"""
request.args(0,default=0,cast=int,otherwise='http://error_url')
request.args(0,default=0,cast=int,otherwise=lambda:...)
"""
n = len(self) n = len(self)
if 0<=i<n or -n<=i<0: if 0<=i<n or -n<=i<0:
value = self[i] value = self[i]
@@ -36,14 +39,17 @@ class List(list):
value = cast(value) value = cast(value)
except (ValueError, TypeError): except (ValueError, TypeError):
from http import HTTP, redirect from http import HTTP, redirect
if url_onerror: if otherwise is None:
redirect(url_onerror)
else:
raise HTTP(404) raise HTTP(404)
elif isinstance(otherwise,str):
redirect(otherwise)
elif callable(otherwise):
return otherwise()
else:
raise RuntimeError, "invalid otherwise"
return value return value
class Storage(dict): class Storage(dict):
""" """
A Storage object is like a dictionary except `obj.foo` can be used A Storage object is like a dictionary except `obj.foo` can be used
in addition to `obj['foo']`, and setting obj.foo = None deletes item foo. in addition to `obj['foo']`, and setting obj.foo = None deletes item foo.
@@ -61,41 +67,31 @@ class Storage(dict):
>>> del o.a >>> del o.a
>>> print o.a >>> print o.a
None
""" """
def __init__(self, *args, **kwargs):
def __getattr__(self, key): self.__dict__ = self
return dict.get(self, key, None) dict.__init__(self, *args, **kwargs)
def __getattr__(self,key):
def __setattr__(self, key, value): return getattr(self,key) if key in self else None
if value is None: def __getitem__(self,key):
if key in self: return dict.get(self,key,None)
del self[key] def copy(self):
else: self.__dict__ = {}
self[key] = value s = Storage(self)
self.__dict__ = self
def __delattr__(self, key): return s
if key in self:
del self[key]
else:
raise AttributeError, "missing key=%s" % key
def __getitem__(self, key):
return dict.get(self, key, None)
def __repr__(self): def __repr__(self):
return '<Storage ' + dict.__repr__(self) + '>' return '<Storage %s>' % dict.__repr__(self)
def __getstate__(self): def __getstate__(self):
return dict(self) return dict(self)
def __setstate__(self, sdict):
def __setstate__(self, value): dict.__init__(self, sdict)
for (k, v) in value.items(): def update(self, *args, **kwargs):
self[k] = v dict.__init__(self, *args, **kwargs)
def getlist(self,key):
def getlist(self, key): """
"""Return a Storage value as a list. Return a Storage value as a list.
If the value is a list it will be returned as-is. If the value is a list it will be returned as-is.
If object is None, an empty list will be returned. If object is None, an empty list will be returned.
@@ -112,17 +108,13 @@ class Storage(dict):
['abc', 'def'] ['abc', 'def']
>>> request.vars.getlist('z') >>> request.vars.getlist('z')
[] []
""" """
value = self.get(key, None) value = getattr(self,key,[])
if isinstance(value, (list, tuple)): return value if not value else \
return value value if isinstance(value,(list,tuple)) else [value]
elif value is None: def getfirst(self,key,default=None):
return [] """
return [value] Return the first or only value when given a request.vars-style key.
def getfirst(self, key):
"""Return the first or only value when given a request.vars-style key.
If the value is a list, its first item will be returned; If the value is a list, its first item will be returned;
otherwise, the value will be returned as-is. otherwise, the value will be returned as-is.
@@ -137,15 +129,13 @@ class Storage(dict):
>>> request.vars.getfirst('y') >>> request.vars.getfirst('y')
'abc' 'abc'
>>> request.vars.getfirst('z') >>> request.vars.getfirst('z')
""" """
value = self.getlist(key) values = self.getlist(default)
if len(value): return values[0] if values else default
return value[0] def getlast(self,key,default=None):
return None """
Returns the last or only single value when
def getlast(self, key): given a request.vars-style key.
"""Returns the last or only single value when given a request.vars-style key.
If the value is a list, the last item will be returned; If the value is a list, the last item will be returned;
otherwise, the value will be returned as-is. otherwise, the value will be returned as-is.
@@ -160,33 +150,25 @@ class Storage(dict):
>>> request.vars.getlast('y') >>> request.vars.getlast('y')
'def' 'def'
>>> request.vars.getlast('z') >>> request.vars.getlast('z')
""" """
value = self.getlist(key) values = self.getlist(default)
if len(value): return values[0] if values else default
return value[-1]
return None
def __getinitargs__(self):
return ()
def __getnewargs__(self):
return ()
PICKABLE = (str,int,long,float,bool,list,dict,tuple,set) PICKABLE = (str,int,long,float,bool,list,dict,tuple,set)
def PickleableStorage(data):
return Storage(dict((k,v) for (k,v) in data.items() if isinstance(v,PICKABLE)))
class StorageList(Storage): class StorageList(Storage):
""" """
like Storage but missing elements default to [] instead of None like Storage but missing elements default to [] instead of None
""" """
def __getitem__(self,key):
return self.__gteattr__(key)
def __getattr__(self, key): def __getattr__(self, key):
if key in self: if key in self:
return self[key] return getattr(self,key)
else: else:
self[key] = [] r = []
return self[key] setattr(self,key,r)
return r
def load_storage(filename): def load_storage(filename):
fp = None fp = None
@@ -197,7 +179,6 @@ def load_storage(filename):
if fp: fp.close() if fp: fp.close()
return Storage(storage) return Storage(storage)
def save_storage(storage, filename): def save_storage(storage, filename):
fp = None fp = None
try: try:
@@ -207,35 +188,31 @@ def save_storage(storage, filename):
if fp: fp.close() if fp: fp.close()
class Settings(Storage): class Settings(Storage):
def __setattr__(self, key, value): def __setattr__(self, key, value):
if key != 'lock_keys' and self.get('lock_keys', None)\ if key != 'lock_keys' and self.lock_keys and not key in self:
and not key in self:
raise SyntaxError, 'setting key \'%s\' does not exist' % key raise SyntaxError, 'setting key \'%s\' does not exist' % key
if key != 'lock_values' and self.get('lock_values', None): if key != 'lock_values' and self.lock_values:
raise SyntaxError, 'setting value cannot be changed: %s' % key raise SyntaxError, 'setting value cannot be changed: %s' % key
self[key] = value Storage.__setattr__(self,key,value)
class Messages(Storage): class Messages(Storage):
def __init__(self, T): def __init__(self, T):
self['T'] = T Storage.__init__(self,T=T)
def __setattr__(self, key, value): def __setattr__(self, key, value):
if key != 'lock_keys' and self.get('lock_keys', None)\ if key != 'lock_keys' and self.lock_keys and not key in self:
and not key in self:
raise SyntaxError, 'setting key \'%s\' does not exist' % key raise SyntaxError, 'setting key \'%s\' does not exist' % key
if key != 'lock_values' and self.get('lock_values', None): if key != 'lock_values' and self.lock_values:
raise SyntaxError, 'setting value cannot be changed: %s' % key raise SyntaxError, 'setting value cannot be changed: %s' % key
self[key] = value Storage.__setattr__(self,key,value)
def __getattr__(self, key): def __getattr__(self, key):
value = self[key] value = Storage.__getattr__(self,key)
if isinstance(value, str): if isinstance(value, str):
return str(self['T'](value)) return str(self.T(value))
return value return value
if __name__ == '__main__': if __name__ == '__main__':
import doctest import doctest
doctest.testmod() doctest.testmod()
@@ -244,3 +221,4 @@ if __name__ == '__main__':