Il 28/04/16 00:26, Val K ha scritto:
> Hi!
> I made mini but useful and universal class to hold json-serializable
> objects.
> Main goal - serialize objects having items-function() as js-objects
>
It looks very interesting to me :)
Thank you for sharing!
I'll notice here if I use it for a little project I have in my mind ;)
Cheers
Manuele
>
> |
> |
> from types import MethodType
> from gluon.contrib import simplejson as sj
>
> class Smart_Storage(dict):
> """
> A Smart_Storage object is like a dictionary but:
> - set/get value:
> obj['foo'] == obj.foo
> - set/get attribute:
> # use `._.` or `._['attr_name']` to set attribute
> obj._.attr = 'I`m attribute but not data!!!'
> obj._['another_attr'] = 'I`m another one'
> # set/update many attributes
> obj._.update(dict(...))
>
> # use dot only to get attribute
> print obj.attr
> # remember that
> obj['any_attr'] == None
> # but don't forget
> obj.__dict__['any_attr'] == obj.any_attr
>
> - bind/call method:
> # use `._['@...']` to bind method
> obj._['@my_meth'] = lambda self: 'I`m method of %s' % self
> # nothing new
> obj.my_meth()
>
> - finally obj.__json__():
> # works recursively
> # for item that is Smart_Storage instance - item.__json__()
> will be applied
> obj.__json__(only = None, exclude = None, values_only = False)
>
> - and obj.__formatters__():
> # use __formatters__ to control serialization *(note double
> quote)*
> obj.__formatters__['key_name'] = lambda self, k, v:
> self.check_access(k) and v or '"-access denied-"'
> # or just
> obj.__formatters__['key_name'] = '"key = %(k)s, value =
> %(v)s"'
> # serialize web2py helpers
> obj.html = DIV()
> obj.__formatters__['html'] = lambda self, k, v: '"%s"' %
> v.xml()
> # serialize js-function/object for embedding as script
> obj.name='John'
> obj.surname='Smith'
> obj.who_are_you = "function(){ console.log( 'I`m',
> this.name, this.surname );}"
> obj.__formatters__['who_are_you'] = '%(v)s' # not '"%(v)s"'
> obj._['@xml'] = lambda self: \
> SCRIPT( '\n'.join([
> 'var obj = %s;',
> 'obj.who_are_you();',
> ]) % self.__json__()
> ).xml()
> ...
> # in the view just
> {{ =obj }}
> # that will be
> <script><!--
> var obj = {"who_are_you":function(){ console.log( 'I`m
> ', this.name, this.surname );},"surname":"Smith","name":"John"};
> obj.who_are_you();
> //--></script>
> """
>
> __getattr__ = dict.get
> __getitem__ = dict.get
> __delattr__ = dict.__delitem__
> __repr__ = lambda self: '<Smart_Storage %s>' % dict.__repr__(self)
>
> class Add_Attr:
>
> def __init__(self, mystor_obj, args=None):
> self.__dict__['mystor_obj'] = mystor_obj
> if args:
> self.update(args)
>
> def __setattr__(self, k, v):
> if k in self.mystor_obj:
> raise RuntimeError('"%s" is in keys' % k)
> self.mystor_obj.__dict__[k] = v
>
> def __setitem__(self, k ,v):
> if k[0] in '0123456789&#.%$':
> raise RuntimeError('"%s" is invalid name' % k)
> if k[0]=='@':
> v = MethodType(v, self.mystor_obj)
> k=k[1:]
> self.__setattr__(k ,v)
>
>
> def update(self, d):
> [self.__setattr__(k, d[k]) for k in d]
>
>
> def __setattr__(self, k, v):
> if k in self.__dict__:
> raise RuntimeError('"%s" is in __dict__' % k)
> dict.__setitem__(self, k, v)
>
> def __init__(self, *a, **kwargs):
> _ = kwargs.pop('_', None)
> if 0:
> self._ = None
> self.__formatters__ = {}
> dict.__init__(self, *a, **kwargs)
> self.__dict__['_'] = Smart_Storage.Add_Attr(self, _)
> self.__dict__['__formatters__'] = {}
>
> def __json_pair__(self, k, v):
> formatter = self.__formatters__.get(k, None)
> if formatter is not None:
> if callable( formatter):
> ret = formatter(self, k, v)
> elif isinstance(formatter, basestring):
> ret = formatter % dict(k=k, v=v)
> else:
> raise RuntimeError('Unsupported formatter for %s :
> "%s"' % (k, formatter))
> else:
> if isinstance(v, Smart_Storage):
> ret = v.__json__()
> elif isinstance(v, (list, tuple)):
> json_lst= [isinstance(it, Smart_Storage) and
> it.__json__() or sj.dumps(it) \
> for it in v]
> ret= '[%s]'% ','.join(json_lst)
> else:
> ret = sj.dumps(v)
>
> return (k, ret)
>
>
> def __json__(self, only = None, exclude = None, values_only = False):
> """
> - only / exclude - filter out keys, 'exclude' applies after
> 'only', so:
> (only = ['a', 'b', 'c'], exclude = ['b']) == (only = ['a',
> 'c'])
> - values_only = True - serialize as json list of values
> """
>
> f_dict = lambda pair: '"%s":%s' % pair
> f_lst = lambda pair: pair[1]
> ret_str, f_str= values_only and ('[%s]' , f_lst) or
> ('{%s}',f_dict)
> buf = []
> if only or exclude:
> keys = only or self
> if exclude:
> keys = set(keys)-set(exclude)
> for k in keys:
> pair = self.__json_pair__(k, self[k])
> if pair:
> buf.append(f_str(pair))
> else:
> for k, v in self.iteritems():
> pair = self.__json_pair__(k,v)
> if pair:
> buf.append(f_str(pair))
> return ret_str % ','.join(buf)
>
> |
>
> |
>
>
> --
> Resources:
> - http://web2py.com
> - http://web2py.com/book (Documentation)
> - http://github.com/web2py/web2py (Source code)
> - https://code.google.com/p/web2py/issues/list (Report Issues)
> ---
> You received this message because you are subscribed to the Google
> Groups "web2py-users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to [email protected]
> <mailto:[email protected]>.
> For more options, visit https://groups.google.com/d/optout.
--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
You received this message because you are subscribed to the Google Groups
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.