From 61a1fb1d58630656d85f485f5195fbd9cd5572cf Mon Sep 17 00:00:00 2001 From: mdipierro Date: Tue, 21 Aug 2012 14:30:02 -0500 Subject: [PATCH] another attempt at new Storage, thanks Jonathan --- VERSION | 2 +- gluon/globals.py | 4 +- gluon/main.py | 5 +- gluon/restricted.py | 1 + gluon/storage.py | 152 +++++++++++++++++++------------------------- 5 files changed, 73 insertions(+), 91 deletions(-) diff --git a/VERSION b/VERSION index d800c35b..9cafffbc 100644 --- a/VERSION +++ b/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 diff --git a/gluon/globals.py b/gluon/globals.py index f8f8abd4..23723731 100644 --- a/gluon/globals.py +++ b/gluon/globals.py @@ -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' diff --git a/gluon/main.py b/gluon/main.py index 6b4d4b20..5aa0f15a 100644 --- a/gluon/main.py +++ b/gluon/main.py @@ -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, "

Temporarily down for maintenance

") - 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 diff --git a/gluon/restricted.py b/gluon/restricted.py index fee54841..770fe48e 100644 --- a/gluon/restricted.py +++ b/gluon/restricted.py @@ -33,6 +33,7 @@ class TicketStorage(Storage): db=None, tablename='web2py_ticket' ): + Storage.__init__(self) self.db = db self.tablename = tablename diff --git a/gluon/storage.py b/gluon/storage.py index b4b73c56..afa32ca6 100644 --- a/gluon/storage.py +++ b/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>> 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 '' - + return '' % 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__': +