another attempt at new Storage, thanks Jonathan
This commit is contained in:
2
VERSION
2
VERSION
@@ -1 +1 @@
|
||||
Version 2.00.0 (2012-08-21 13:38:21) dev
|
||||
Version 2.00.0 (2012-08-21 14:29:57) dev
|
||||
|
||||
@@ -83,6 +83,7 @@ class Request(Storage):
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
Storage.__init__(self)
|
||||
self.wsgi = Storage() # hooks to environ and start_response
|
||||
self.env = Storage()
|
||||
self.cookies = Cookie.SimpleCookie()
|
||||
@@ -100,7 +101,7 @@ class Request(Storage):
|
||||
self.is_https = False
|
||||
self.is_local = False
|
||||
self.global_settings = settings.global_settings
|
||||
|
||||
|
||||
def compute_uuid(self):
|
||||
self.uuid = '%s/%s.%s.%s' % (
|
||||
self.application,
|
||||
@@ -165,6 +166,7 @@ class Response(Storage):
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
Storage.__init__(self)
|
||||
self.status = 200
|
||||
self.headers = dict()
|
||||
self.headers['X-Powered-By'] = 'web2py'
|
||||
|
||||
@@ -446,8 +446,9 @@ def wsgibase(environ, responder):
|
||||
elif not request.is_local and \
|
||||
os.path.exists(os.path.join(request.folder,'DISABLED')):
|
||||
raise HTTP(503, "<html><body><h1>Temporarily down for maintenance</h1></body></html>")
|
||||
request.url = Url(r=request, args=request.args,
|
||||
extension=request.raw_extension)
|
||||
request.url = Url(r=request,
|
||||
args=request.args,
|
||||
extension=request.raw_extension)
|
||||
|
||||
# ##################################################
|
||||
# build missing folders
|
||||
|
||||
@@ -33,6 +33,7 @@ class TicketStorage(Storage):
|
||||
db=None,
|
||||
tablename='web2py_ticket'
|
||||
):
|
||||
Storage.__init__(self)
|
||||
self.db = db
|
||||
self.tablename = tablename
|
||||
|
||||
|
||||
152
gluon/storage.py
152
gluon/storage.py
@@ -13,9 +13,8 @@ Provides:
|
||||
"""
|
||||
|
||||
import cPickle
|
||||
import portalocker
|
||||
|
||||
__all__ = ['List', 'Storage', 'Settings', 'Messages', 'PickleableStorage',
|
||||
__all__ = ['List', 'Storage', 'Settings', 'Messages',
|
||||
'StorageList', 'load_storage', 'save_storage']
|
||||
|
||||
|
||||
@@ -25,7 +24,11 @@ class List(list):
|
||||
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)
|
||||
if 0<=i<n or -n<=i<0:
|
||||
value = self[i]
|
||||
@@ -36,14 +39,17 @@ class List(list):
|
||||
value = cast(value)
|
||||
except (ValueError, TypeError):
|
||||
from http import HTTP, redirect
|
||||
if url_onerror:
|
||||
redirect(url_onerror)
|
||||
else:
|
||||
if otherwise is None:
|
||||
raise HTTP(404)
|
||||
elif isinstance(otherwise,str):
|
||||
redirect(otherwise)
|
||||
elif callable(otherwise):
|
||||
return otherwise()
|
||||
else:
|
||||
raise RuntimeError, "invalid otherwise"
|
||||
return value
|
||||
|
||||
class Storage(dict):
|
||||
|
||||
"""
|
||||
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.
|
||||
@@ -61,41 +67,31 @@ class Storage(dict):
|
||||
|
||||
>>> del o.a
|
||||
>>> print o.a
|
||||
None
|
||||
|
||||
|
||||
"""
|
||||
|
||||
def __getattr__(self, key):
|
||||
return dict.get(self, key, None)
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
if value is None:
|
||||
if key in self:
|
||||
del self[key]
|
||||
else:
|
||||
self[key] = value
|
||||
|
||||
def __delattr__(self, key):
|
||||
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 __init__(self, *args, **kwargs):
|
||||
self.__dict__ = self
|
||||
dict.__init__(self, *args, **kwargs)
|
||||
def __getattr__(self,key):
|
||||
return getattr(self,key) if key in self else None
|
||||
def __getitem__(self,key):
|
||||
return dict.get(self,key,None)
|
||||
def copy(self):
|
||||
self.__dict__ = {}
|
||||
s = Storage(self)
|
||||
self.__dict__ = self
|
||||
return s
|
||||
def __repr__(self):
|
||||
return '<Storage ' + dict.__repr__(self) + '>'
|
||||
|
||||
return '<Storage %s>' % dict.__repr__(self)
|
||||
def __getstate__(self):
|
||||
return dict(self)
|
||||
|
||||
def __setstate__(self, value):
|
||||
for (k, v) in value.items():
|
||||
self[k] = v
|
||||
|
||||
def getlist(self, key):
|
||||
"""Return a Storage value as a list.
|
||||
def __setstate__(self, sdict):
|
||||
dict.__init__(self, sdict)
|
||||
def update(self, *args, **kwargs):
|
||||
dict.__init__(self, *args, **kwargs)
|
||||
def getlist(self,key):
|
||||
"""
|
||||
Return a Storage value as a list.
|
||||
|
||||
If the value is a list it will be returned as-is.
|
||||
If object is None, an empty list will be returned.
|
||||
@@ -112,17 +108,13 @@ class Storage(dict):
|
||||
['abc', 'def']
|
||||
>>> request.vars.getlist('z')
|
||||
[]
|
||||
|
||||
"""
|
||||
value = self.get(key, None)
|
||||
if isinstance(value, (list, tuple)):
|
||||
return value
|
||||
elif value is None:
|
||||
return []
|
||||
return [value]
|
||||
|
||||
def getfirst(self, key):
|
||||
"""Return the first or only value when given a request.vars-style key.
|
||||
value = getattr(self,key,[])
|
||||
return value if not value else \
|
||||
value if isinstance(value,(list,tuple)) else [value]
|
||||
def getfirst(self,key,default=None):
|
||||
"""
|
||||
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;
|
||||
otherwise, the value will be returned as-is.
|
||||
@@ -137,15 +129,13 @@ class Storage(dict):
|
||||
>>> request.vars.getfirst('y')
|
||||
'abc'
|
||||
>>> request.vars.getfirst('z')
|
||||
|
||||
"""
|
||||
value = self.getlist(key)
|
||||
if len(value):
|
||||
return value[0]
|
||||
return None
|
||||
|
||||
def getlast(self, key):
|
||||
"""Returns the last or only single value when given a request.vars-style key.
|
||||
values = self.getlist(default)
|
||||
return values[0] if values else default
|
||||
def getlast(self,key,default=None):
|
||||
"""
|
||||
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;
|
||||
otherwise, the value will be returned as-is.
|
||||
@@ -160,33 +150,25 @@ class Storage(dict):
|
||||
>>> request.vars.getlast('y')
|
||||
'def'
|
||||
>>> request.vars.getlast('z')
|
||||
|
||||
"""
|
||||
value = self.getlist(key)
|
||||
if len(value):
|
||||
return value[-1]
|
||||
return None
|
||||
|
||||
def __getinitargs__(self):
|
||||
return ()
|
||||
|
||||
def __getnewargs__(self):
|
||||
return ()
|
||||
values = self.getlist(default)
|
||||
return values[0] if values else default
|
||||
|
||||
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):
|
||||
"""
|
||||
like Storage but missing elements default to [] instead of None
|
||||
"""
|
||||
def __getitem__(self,key):
|
||||
return self.__gteattr__(key)
|
||||
def __getattr__(self, key):
|
||||
if key in self:
|
||||
return self[key]
|
||||
return getattr(self,key)
|
||||
else:
|
||||
self[key] = []
|
||||
return self[key]
|
||||
r = []
|
||||
setattr(self,key,r)
|
||||
return r
|
||||
|
||||
def load_storage(filename):
|
||||
fp = None
|
||||
@@ -197,7 +179,6 @@ def load_storage(filename):
|
||||
if fp: fp.close()
|
||||
return Storage(storage)
|
||||
|
||||
|
||||
def save_storage(storage, filename):
|
||||
fp = None
|
||||
try:
|
||||
@@ -207,35 +188,31 @@ def save_storage(storage, filename):
|
||||
if fp: fp.close()
|
||||
|
||||
class Settings(Storage):
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
if key != 'lock_keys' and self.get('lock_keys', None)\
|
||||
and not key in self:
|
||||
if key != 'lock_keys' and self.lock_keys and not key in self:
|
||||
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
|
||||
self[key] = value
|
||||
|
||||
Storage.__setattr__(self,key,value)
|
||||
|
||||
class Messages(Storage):
|
||||
|
||||
def __init__(self, T):
|
||||
self['T'] = T
|
||||
Storage.__init__(self,T=T)
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
if key != 'lock_keys' and self.get('lock_keys', None)\
|
||||
and not key in self:
|
||||
if key != 'lock_keys' and self.lock_keys and not key in self:
|
||||
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
|
||||
self[key] = value
|
||||
Storage.__setattr__(self,key,value)
|
||||
|
||||
def __getattr__(self, key):
|
||||
value = self[key]
|
||||
value = Storage.__getattr__(self,key)
|
||||
if isinstance(value, str):
|
||||
return str(self['T'](value))
|
||||
return str(self.T(value))
|
||||
return value
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
@@ -244,3 +221,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user