source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/gluon/serializers.py @ 42095c5

mainqndtest v1.1.1
Last change on this file since 42095c5 was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 7.9 KB
Line 
1"""
2This file is part of the web2py Web Framework
3Copyrighted by Massimo Di Pierro <mdipierro@cs.depaul.edu>
4License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
5"""
6import datetime
7import decimal
8from gluon.storage import Storage
9from gluon.html import TAG, XmlComponent, xmlescape
10from gluon.languages import lazyT
11import gluon.contrib.rss2 as rss2
12import json as json_parser
13from gluon._compat import long, to_native, unicodeT, integer_types
14
15have_yaml = True
16try:
17    import yaml as yamlib
18except ImportError:
19    have_yaml = False
20
21
22def cast_keys(o, cast=str, encoding="utf-8"):
23    """
24    Builds a new object with <cast> type keys.
25    Use this function if you are in Python < 2.6.5
26    This avoids syntax errors when unpacking dictionary arguments.
27
28    Args:
29        o: is the object input
30        cast:  (defaults to str) is an object type or function
31            which supports conversion such as:
32
33                converted = cast(o)
34
35        encoding: (defaults to utf-8) is the encoding for unicode
36            keys. This is not used for custom cast functions
37
38    """
39
40    if isinstance(o, (dict, Storage)):
41        if isinstance(o, dict):
42            newobj = dict()
43        else:
44            newobj = Storage()
45        for k, v in o.items():
46            if (cast == str) and isinstance(k, unicodeT):
47                key = k.encode(encoding)
48            else:
49                key = cast(k)
50            newobj[key] = cast_keys(v, cast=cast, encoding=encoding)
51    elif isinstance(o, (tuple, set, list)):
52        newobj = []
53        for item in o:
54            newobj.append(cast_keys(item, cast=cast, encoding=encoding))
55        if isinstance(o, tuple):
56            newobj = tuple(newobj)
57        elif isinstance(o, set):
58            newobj = set(newobj)
59    else:
60        # no string cast (unknown object)
61        newobj = o
62    return newobj
63
64
65def loads_json(o, unicode_keys=True, **kwargs):
66    # deserialize a json string
67    result = json_parser.loads(o, **kwargs)
68    if not unicode_keys:
69        # filter non-str keys in dictionary objects
70        result = cast_keys(result,
71                           encoding=kwargs.get("encoding", "utf-8"))
72    return result
73
74
75def custom_json(o):
76    if hasattr(o, 'custom_json') and callable(o.custom_json):
77        return o.custom_json()
78    if isinstance(o, (datetime.date,
79                      datetime.datetime,
80                      datetime.time)):
81        return o.isoformat()[:19].replace('T', ' ')
82    elif isinstance(o, integer_types):
83        return int(o)
84    elif isinstance(o, decimal.Decimal):
85        return float(o)
86    elif isinstance(o, (bytes, bytearray)):
87        return str(o)
88    elif isinstance(o, lazyT):
89        return str(o)
90    elif isinstance(o, XmlComponent):
91        return to_native(o.xml())
92    elif isinstance(o, set):
93        return list(o)
94    elif hasattr(o, 'as_list') and callable(o.as_list):
95        return o.as_list()
96    elif hasattr(o, 'as_dict') and callable(o.as_dict):
97        return o.as_dict()
98    else:
99        raise TypeError(repr(o) + " is not JSON serializable")
100
101
102def xml_rec(value, key, quote=True):
103    if hasattr(value, 'custom_xml') and callable(value.custom_xml):
104        return value.custom_xml()
105    elif isinstance(value, (dict, Storage)):
106        return TAG[key](*[TAG[k](xml_rec(v, '', quote))
107                          for k, v in value.items()])
108    elif isinstance(value, list):
109        return TAG[key](*[TAG.item(xml_rec(item, '', quote)) for item in value])
110    elif hasattr(value, 'as_list') and callable(value.as_list):
111        return str(xml_rec(value.as_list(), '', quote))
112    elif hasattr(value, 'as_dict') and callable(value.as_dict):
113        return str(xml_rec(value.as_dict(), '', quote))
114    else:
115        return xmlescape(value, quote)
116
117
118def xml(value, encoding='UTF-8', key='document', quote=True):
119    return ('<?xml version="1.0" encoding="%s"?>' % encoding) + str(xml_rec(value, key, quote))
120
121
122class JSONEncoderForHTML(json_parser.JSONEncoder):
123    """An encoder that produces JSON safe to embed in HTML.
124    To embed JSON content in, say, a script tag on a web page, the
125    characters &, < and > should be escaped. They cannot be escaped
126    with the usual entities (e.g. &amp;) because they are not expanded
127    within <script> tags.
128    This class also escapes the line separator and paragraph separator
129    characters U+2028 and U+2029, irrespective of the ensure_ascii setting,
130    as these characters are not valid in JavaScript strings (see
131    http://timelessrepo.com/json-isnt-a-javascript-subset).
132    """
133
134    def encode(self, o):
135        # Override JSONEncoder.encode because it has hacks for
136        # performance that make things more complicated.
137        chunks = self.iterencode(o, True)
138        if self.ensure_ascii:
139            return ''.join(chunks)
140        else:
141            return u''.join(chunks)
142
143    def iterencode(self, o, _one_shot=False):
144        chunks = super(JSONEncoderForHTML, self).iterencode(o, _one_shot)
145        for chunk in chunks:
146            chunk = chunk.replace('&', '\\u0026')
147            chunk = chunk.replace('<', '\\u003c')
148            chunk = chunk.replace('>', '\\u003e')
149
150            if not self.ensure_ascii:
151                chunk = chunk.replace(u'\u2028', '\\u2028')
152                chunk = chunk.replace(u'\u2029', '\\u2029')
153
154            yield chunk
155
156
157def json(value, default=custom_json, indent=None, sort_keys=False, cls=JSONEncoderForHTML):
158    return json_parser.dumps(value, default=default, cls=cls, sort_keys=sort_keys, indent=indent)
159
160def csv(value):
161    return ''
162
163
164def ics(events, title=None, link=None, timeshift=0, calname=True,
165        **ignored):
166    title = title or '(unknown)'
167    if link and not callable(link):
168        link = lambda item, prefix=link: prefix.replace(
169            '[id]', str(item['id']))
170    s = 'BEGIN:VCALENDAR'
171    s += '\nVERSION:2.0'
172    if not calname is False:
173        s += '\nX-WR-CALNAME:%s' % (calname or title)
174    s += '\nSUMMARY:%s' % title
175    s += '\nPRODID:Generated by web2py'
176    s += '\nCALSCALE:GREGORIAN'
177    s += '\nMETHOD:PUBLISH'
178    for item in events:
179        s += '\nBEGIN:VEVENT'
180        s += '\nUID:%s' % item['id']
181        if link:
182            s += '\nURL:%s' % link(item)
183        shift = datetime.timedelta(seconds=3600 * timeshift)
184        start = item['start_datetime'] + shift
185        stop = item['stop_datetime'] + shift
186        s += '\nDTSTART:%s' % start.strftime('%Y%m%dT%H%M%S')
187        s += '\nDTEND:%s' % stop.strftime('%Y%m%dT%H%M%S')
188        s += '\nSUMMARY:%s' % item['title']
189        s += '\nEND:VEVENT'
190    s += '\nEND:VCALENDAR'
191    return s
192
193def safe_encode(text):
194    if not isinstance(text, (str, unicodeT)):
195        text = str(text)
196    try:
197        text = text.encode('utf8','replace')
198    except ValueError:
199        new_text = ''
200        for c in text:
201            try:
202                new_text += c.encode('utf8')
203            except:
204                new_text += '?'
205        text = new_text
206    return text
207
208def rss(feed):
209    if not 'entries' in feed and 'items' in feed:
210        feed['entries'] = feed['items']
211
212    def safestr(obj, key, default=''):
213        return safe_encode(obj.get(key,''))
214
215    now = datetime.datetime.now()
216    rss = rss2.RSS2(title=safestr(feed,'title'),
217                    link=safestr(feed,'link'),
218                    description=safestr(feed,'description'),
219                    lastBuildDate=feed.get('created_on', now),
220                    items=[rss2.RSSItem(
221                           title=safestr(entry,'title','(notitle)'),
222                           link=safestr(entry,'link'),
223                           description=safestr(entry,'description'),
224                           pubDate=entry.get('created_on', now)
225                           ) for entry in feed.get('entries', [])])
226    return rss.to_xml(encoding='utf8')
227
228
229def yaml(data):
230    if have_yaml:
231        return yamlib.dump(data)
232    else:
233        raise ImportError("No YAML serializer available")
234
235
236def loads_yaml(data):
237    if have_yaml:
238        return yamlib.load(data)
239    else:
240        raise ImportError("No YAML serializer available")
Note: See TracBrowser for help on using the repository browser.