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
15 except ImportError:
16 try:
17 import json as json_parser
18 except:
19 import gluon.contrib.simplejson as json_parser
20
21 have_yaml = True
22 try:
23 import yaml as yamlib
24 except ImportError:
25 have_yaml = False
26
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
65 newobj = o
66 return newobj
67
69
70 result = json_parser.loads(o, **kwargs)
71 if not unicode_keys:
72
73 result = cast_keys(result,
74 encoding=kwargs.get("encoding", "utf-8"))
75 return result
76
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
121
122
123 return json_parser.dumps(value,
124 default=default).replace(ur'\u2028',
125 '\\u2028').replace(ur'\2029',
126 '\\u2029')
127
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
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
181 if have_yaml:
182 return yamlib.dump(data)
183 else: raise ImportError("No YAML serializer available")
184
186 if have_yaml:
187 return yamlib.load(data)
188 else: raise ImportError("No YAML serializer available")
189