Mercurial > libervia-backend
comparison sat/tools/common/data_objects.py @ 2562:26edcf3a30eb
core, setup: huge cleaning:
- moved directories from src and frontends/src to sat and sat_frontends, which is the recommanded naming convention
- move twisted directory to root
- removed all hacks from setup.py, and added missing dependencies, it is now clean
- use https URL for website in setup.py
- removed "Environment :: X11 Applications :: GTK", as wix is deprecated and removed
- renamed sat.sh to sat and fixed its installation
- added python_requires to specify Python version needed
- replaced glib2reactor which use deprecated code by gtk3reactor
sat can now be installed directly from virtualenv without using --system-site-packages anymore \o/
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 02 Apr 2018 19:44:50 +0200 |
parents | src/tools/common/data_objects.py@8cf58a415126 |
children | 56f94936df1e |
comparison
equal
deleted
inserted
replaced
2561:bd30dc3ffe5a | 2562:26edcf3a30eb |
---|---|
1 #!/usr/bin/env python2 | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # SAT: a jabber client | |
5 # Copyright (C) 2009-2018 Jérôme Poisson (goffi@goffi.org) | |
6 | |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 """Objects handling bridge data, with jinja2 safe markup handling""" | |
21 | |
22 from sat.tools.common import data_format | |
23 try: | |
24 from jinja2 import Markup as safe | |
25 except ImportError: | |
26 safe = unicode | |
27 | |
28 from sat.tools.common import uri as xmpp_uri | |
29 import urllib | |
30 | |
31 q = lambda value: urllib.quote(value.encode('utf-8'), safe='@') | |
32 | |
33 | |
34 class BlogItem(object): | |
35 | |
36 def __init__(self, mb_data, parent): | |
37 self.mb_data = mb_data | |
38 self.parent = parent | |
39 self._tags = None | |
40 self._groups = None | |
41 self._comments = None | |
42 self._comments_items_list = None | |
43 | |
44 @property | |
45 def id(self): | |
46 return self.mb_data.get(u'id') | |
47 | |
48 @property | |
49 def atom_id(self): | |
50 return self.mb_data.get(u'atom_id') | |
51 | |
52 @property | |
53 def uri(self): | |
54 node = self.parent.node | |
55 service = self.parent.service | |
56 return xmpp_uri.buildXMPPUri(u'pubsub', | |
57 subtype=u'microblog', | |
58 path=service, | |
59 node=node, | |
60 item=self.id) | |
61 | |
62 @property | |
63 def published(self): | |
64 return self.mb_data.get(u'published') | |
65 | |
66 @property | |
67 def updated(self): | |
68 return self.mb_data.get(u'updated') | |
69 | |
70 @property | |
71 def language(self): | |
72 return self.mb_data.get(u'language') | |
73 | |
74 @property | |
75 def author(self): | |
76 return self.mb_data.get(u'author') | |
77 | |
78 @property | |
79 def author_jid(self): | |
80 return self.mb_data.get(u'author_jid') | |
81 | |
82 @property | |
83 def author_jid_verified(self): | |
84 return self.mb_data.get(u'author_jid_verified') | |
85 | |
86 @property | |
87 def author_email(self): | |
88 return self.mb_data.get(u'author_email') | |
89 | |
90 @property | |
91 def tags(self): | |
92 if self._tags is None: | |
93 self._tags = list(data_format.dict2iter('tag', self.mb_data)) | |
94 return self._tags | |
95 | |
96 @property | |
97 def groups(self): | |
98 if self._groups is None: | |
99 self._groups = list(data_format.dict2iter('group', self.mb_data)) | |
100 return self._groups | |
101 | |
102 @property | |
103 def title(self): | |
104 return self.mb_data.get(u'title') | |
105 | |
106 @property | |
107 def title_xhtml(self): | |
108 try: | |
109 return safe(self.mb_data[u'title_xhtml']) | |
110 except KeyError: | |
111 return None | |
112 | |
113 @property | |
114 def content(self): | |
115 return self.mb_data.get(u'content') | |
116 | |
117 @property | |
118 def content_xhtml(self): | |
119 try: | |
120 return safe(self.mb_data[u'content_xhtml']) | |
121 except KeyError: | |
122 return None | |
123 | |
124 @property | |
125 def comments(self): | |
126 if self._comments is None: | |
127 self._comments = data_format.dict2iterdict(u'comments', self.mb_data, (u'node', u'service')) | |
128 return self._comments | |
129 | |
130 @property | |
131 def comments_service(self): | |
132 return self.mb_data.get(u'comments_service') | |
133 | |
134 @property | |
135 def comments_node(self): | |
136 return self.mb_data.get(u'comments_node') | |
137 | |
138 @property | |
139 def comments_items_list(self): | |
140 return [] if self._comments_items_list is None else self._comments_items_list | |
141 | |
142 def appendCommentsItems(self, items): | |
143 """append comments items to self.comments_items""" | |
144 if self._comments_items_list is None: | |
145 self._comments_items_list = [] | |
146 self._comments_items_list.append(items) | |
147 | |
148 | |
149 class BlogItems(object): | |
150 | |
151 def __init__(self, mb_data): | |
152 self.items = [BlogItem(i, self) for i in mb_data[0]] | |
153 self.metadata = mb_data[1] | |
154 | |
155 @property | |
156 def service(self): | |
157 return self.metadata[u'service'] | |
158 | |
159 @property | |
160 def node(self): | |
161 return self.metadata[u'node'] | |
162 | |
163 @property | |
164 def uri(self): | |
165 return self.metadata[u'uri'] | |
166 | |
167 def __len__(self): | |
168 return self.items.__len__() | |
169 | |
170 def __missing__(self, key): | |
171 return self.items.__missing__(key) | |
172 | |
173 def __getitem__(self, key): | |
174 return self.items.__getitem__(key) | |
175 | |
176 def __iter__(self): | |
177 return self.items.__iter__() | |
178 | |
179 def __reversed__(self): | |
180 return self.items.__reversed__() | |
181 | |
182 def __contains__(self, item): | |
183 return self.items.__contains__(item) | |
184 | |
185 | |
186 class Message(object): | |
187 | |
188 def __init__(self, msg_data): | |
189 self._uid = msg_data[0] | |
190 self._timestamp = msg_data[1] | |
191 self._from_jid = msg_data[2] | |
192 self._to_jid = msg_data[3] | |
193 self._message_data = msg_data[4] | |
194 self._subject_data = msg_data[5] | |
195 self._type = msg_data[6] | |
196 self._extra = msg_data[7] | |
197 self._html = dict(data_format.getSubDict('xhtml', self._extra)) | |
198 | |
199 @property | |
200 def id(self): | |
201 return self._uid | |
202 | |
203 @property | |
204 def timestamp(self): | |
205 return self._timestamp | |
206 | |
207 @property | |
208 def from_(self): | |
209 return self._from_jid | |
210 | |
211 @property | |
212 def text(self): | |
213 try: | |
214 return self._message_data[''] | |
215 except KeyError: | |
216 return next(self._message_data.itervalues()) | |
217 | |
218 @property | |
219 def subject(self): | |
220 try: | |
221 return self._subject_data[''] | |
222 except KeyError: | |
223 return next(self._subject_data.itervalues()) | |
224 | |
225 @property | |
226 def type(self): | |
227 return self._type | |
228 | |
229 @property | |
230 def thread(self): | |
231 return self._extra.get('thread') | |
232 | |
233 @property | |
234 def thread_parent(self): | |
235 return self._extra.get('thread_parent') | |
236 | |
237 @property | |
238 def received(self): | |
239 return self._extra.get('received_timestamp', self._timestamp) | |
240 | |
241 @property | |
242 def delay_sender(self): | |
243 return self._extra.get('delay_sender') | |
244 | |
245 @property | |
246 def info_type(self): | |
247 return self._extra.get('info_type') | |
248 | |
249 @property | |
250 def html(self): | |
251 if not self._html: | |
252 return None | |
253 try: | |
254 return safe(self._html['']) | |
255 except KeyError: | |
256 return safe(next(self._html.itervalues())) | |
257 | |
258 | |
259 class Messages(object): | |
260 | |
261 def __init__(self, msgs_data): | |
262 self.messages = [Message(m) for m in msgs_data] | |
263 | |
264 def __len__(self): | |
265 return self.messages.__len__() | |
266 | |
267 def __missing__(self, key): | |
268 return self.messages.__missing__(key) | |
269 | |
270 def __getitem__(self, key): | |
271 return self.messages.__getitem__(key) | |
272 | |
273 def __iter__(self): | |
274 return self.messages.__iter__() | |
275 | |
276 def __reversed__(self): | |
277 return self.messages.__reversed__() | |
278 | |
279 def __contains__(self, item): | |
280 return self.messages.__contains__(item) | |
281 | |
282 class Room(object): | |
283 | |
284 def __init__(self, jid, name=None, url=None): | |
285 self.jid = jid | |
286 self.name = name or jid | |
287 if url is not None: | |
288 self.url = url | |
289 | |
290 | |
291 class Identity(object): | |
292 | |
293 def __init__(self, jid_str, data=None): | |
294 self.jid_str = jid_str | |
295 self.data = data if data is not None else {} | |
296 | |
297 def __getitem__(self, key): | |
298 return self.data[key] | |
299 | |
300 def __getattr__(self, key): | |
301 try: | |
302 return self.data[key] | |
303 except KeyError: | |
304 raise AttributeError(key) | |
305 | |
306 | |
307 class Identities(object): | |
308 | |
309 def __init__(self): | |
310 self.identities = {} | |
311 | |
312 def __getitem__(self, jid_str): | |
313 try: | |
314 return self.identities[jid_str] | |
315 except KeyError: | |
316 return None | |
317 | |
318 def __setitem__(self, jid_str, data): | |
319 self.identities[jid_str] = Identity(jid_str, data) | |
320 | |
321 def __contains__(self, jid_str): | |
322 return jid_str in self.identities | |
323 | |
324 | |
325 class ObjectQuoter(object): | |
326 """object wrapper which quote attribues (to be used in templates)""" | |
327 | |
328 def __init__(self, obj): | |
329 self.obj = obj | |
330 | |
331 def __unicode__(self): | |
332 return q(self.obj.__unicode__()) | |
333 | |
334 def __str__(self): | |
335 return self.__unicode__() | |
336 | |
337 def __getattr__(self, name): | |
338 return q(self.obj.__getattr__(name)) | |
339 | |
340 def __getitem__(self, key): | |
341 return q(self.obj.__getitem__(key)) | |
342 | |
343 | |
344 class OnClick(object): | |
345 """Class to handle clickable elements targets""" | |
346 | |
347 def __init__(self, url=None): | |
348 self.url = url | |
349 | |
350 def formatUrl(self, *args, **kwargs): | |
351 """format URL using Python formatting | |
352 | |
353 values will be quoted before being used | |
354 """ | |
355 return self.url.format(*[q(a) for a in args], | |
356 **{k: ObjectQuoter(v) for k,v in kwargs.iteritems()}) |