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