Package gluon :: Module serializers
[hide private]
[frames] | no frames]

Source Code for Module gluon.serializers

  1  """ 
  2  This file is part of the web2py Web Framework 
  3  Copyrighted by Massimo Di Pierro <mdipierro@cs.depaul.edu> 
  4  License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html) 
  5  """ 
  6  import datetime 
  7  import decimal 
  8  from gluon.storage import Storage 
  9  from gluon.html import TAG, XmlComponent, xmlescape 
 10  from gluon.languages import lazyT 
 11  import gluon.contrib.rss2 as rss2 
 12   
 13  try: 
 14      import simplejson as json_parser                # try external module 
 15  except ImportError: 
 16      try: 
 17          import json as json_parser                  # try stdlib (Python >= 2.6) 
 18      except: 
 19          import gluon.contrib.simplejson as json_parser    # fallback to pure-Python module 
 20   
 21  have_yaml = True 
 22  try: 
 23      import yaml as yamlib 
 24  except ImportError: 
 25      have_yaml = False 
 26   
27 -def cast_keys(o, cast=str, encoding="utf-8"):
28 """ Builds a new object with <cast> type keys 29 30 Arguments: 31 o is the object input 32 cast (defaults to str) is an object type or function 33 which supports conversion such as: 34 35 >>> converted = cast(o) 36 37 encoding (defaults to utf-8) is the encoding for unicode 38 keys. This is not used for custom cast functions 39 40 Use this funcion if you are in Python < 2.6.5 41 This avoids syntax errors when unpacking dictionary arguments. 42 """ 43 44 if isinstance(o, (dict, Storage)): 45 if isinstance(o, dict): 46 newobj = dict() 47 else: 48 newobj = Storage() 49 for k, v in o.items(): 50 if (cast == str) and isinstance(k, unicode): 51 key = k.encode(encoding) 52 else: 53 key = cast(k) 54 newobj[key] = cast_keys(v, cast=cast, encoding=encoding) 55 elif isinstance(o, (tuple, set, list)): 56 newobj = [] 57 for item in o: 58 newobj.append(cast_keys(item, cast=cast, encoding=encoding)) 59 if isinstance(o, tuple): 60 newobj = tuple(newobj) 61 elif isinstance(o, set): 62 newobj = set(newobj) 63 else: 64 # no string cast (unknown object) 65 newobj = o 66 return newobj
67
68 -def loads_json(o, unicode_keys=True, **kwargs):
69 # deserialize a json string 70 result = json_parser.loads(o, **kwargs) 71 if not unicode_keys: 72 # filter non-str keys in dictionary objects 73 result = cast_keys(result, 74 encoding=kwargs.get("encoding", "utf-8")) 75 return result
76
77 -def custom_json(o):
78 if hasattr(o, 'custom_json') and callable(o.custom_json): 79 return o.custom_json() 80 if isinstance(o, (datetime.date, 81 datetime.datetime, 82 datetime.time)): 83 return o.isoformat()[:19].replace('T', ' ') 84 elif isinstance(o, (int, long)): 85 return int(o) 86 elif isinstance(o, decimal.Decimal): 87 return str(o) 88 elif isinstance(o, lazyT): 89 return str(o) 90 elif isinstance(o, XmlComponent): 91 return str(o) 92 elif hasattr(o, 'as_list') and callable(o.as_list): 93 return o.as_list() 94 elif hasattr(o, 'as_dict') and callable(o.as_dict): 95 return o.as_dict() 96 else: 97 raise TypeError(repr(o) + " is not JSON serializable")
98 99
100 -def xml_rec(value, key, quote=True):
101 if hasattr(value, 'custom_xml') and callable(value.custom_xml): 102 return value.custom_xml() 103 elif isinstance(value, (dict, Storage)): 104 return TAG[key](*[TAG[k](xml_rec(v, '', quote)) 105 for k, v in value.items()]) 106 elif isinstance(value, list): 107 return TAG[key](*[TAG.item(xml_rec(item, '', quote)) for item in value]) 108 elif hasattr(value, 'as_list') and callable(value.as_list): 109 return str(xml_rec(value.as_list(), '', quote)) 110 elif hasattr(value, 'as_dict') and callable(value.as_dict): 111 return str(xml_rec(value.as_dict(), '', quote)) 112 else: 113 return xmlescape(value, quote)
114 115
116 -def xml(value, encoding='UTF-8', key='document', quote=True):
117 return ('<?xml version="1.0" encoding="%s"?>' % encoding) + str(xml_rec(value, key, quote))
118 119
120 -def json(value, default=custom_json):
121 # replace JavaScript incompatible spacing 122 # http://timelessrepo.com/json-isnt-a-javascript-subset 123 return json_parser.dumps(value, 124 default=default).replace(ur'\u2028', 125 '\\u2028').replace(ur'\2029', 126 '\\u2029')
127
128 -def csv(value):
129 return ''
130 131
132 -def ics(events, title=None, link=None, timeshift=0, calname=True, 133 **ignored):
134 import datetime 135 title = title or '(unknown)' 136 if link and not callable(link): 137 link = lambda item, prefix=link: prefix.replace( 138 '[id]', str(item['id'])) 139 s = 'BEGIN:VCALENDAR' 140 s += '\nVERSION:2.0' 141 if not calname is False: 142 s += '\nX-WR-CALNAME:%s' % (calname or title) 143 s += '\nSUMMARY:%s' % title 144 s += '\nPRODID:Generated by web2py' 145 s += '\nCALSCALE:GREGORIAN' 146 s += '\nMETHOD:PUBLISH' 147 for item in events: 148 s += '\nBEGIN:VEVENT' 149 s += '\nUID:%s' % item['id'] 150 if link: 151 s += '\nURL:%s' % link(item) 152 shift = datetime.timedelta(seconds=3600 * timeshift) 153 start = item['start_datetime'] + shift 154 stop = item['stop_datetime'] + shift 155 s += '\nDTSTART:%s' % start.strftime('%Y%m%dT%H%M%S') 156 s += '\nDTEND:%s' % stop.strftime('%Y%m%dT%H%M%S') 157 s += '\nSUMMARY:%s' % item['title'] 158 s += '\nEND:VEVENT' 159 s += '\nEND:VCALENDAR' 160 return s
161 162
163 -def rss(feed):
164 if not 'entries' in feed and 'items' in feed: 165 feed['entries'] = feed['items'] 166 now = datetime.datetime.now() 167 rss = rss2.RSS2(title=str(feed.get('title', '(notitle)').encode('utf-8', 'replace')), 168 link=str(feed.get('link', None).encode('utf-8', 'replace')), 169 description=str(feed.get('description', '').encode('utf-8', 'replace')), 170 lastBuildDate=feed.get('created_on', now), 171 items=[rss2.RSSItem( 172 title=str(entry.get('title', '(notitle)').encode('utf-8', 'replace')), 173 link=str(entry.get('link', None).encode('utf-8', 'replace')), 174 description=str(entry.get('description', '').encode('utf-8', 'replace')), 175 pubDate=entry.get('created_on', now) 176 ) for entry in feed.get('entries', [])]) 177 return rss.to_xml(encoding='utf-8')
178 179
180 -def yaml(data):
181 if have_yaml: 182 return yamlib.dump(data) 183 else: raise ImportError("No YAML serializer available")
184
185 -def loads_yaml(data):
186 if have_yaml: 187 return yamlib.load(data) 188 else: raise ImportError("No YAML serializer available")
189