comparison sat/plugins/plugin_exp_pubsub_schema.py @ 2624:56f94936df1e

code style reformatting using black
author Goffi <goffi@goffi.org>
date Wed, 27 Jun 2018 20:14:46 +0200
parents 3e4e78de9cca
children 3480d4fdf83a
comparison
equal deleted inserted replaced
2623:49533de4540b 2624:56f94936df1e
25 from sat.tools.common import date_utils 25 from sat.tools.common import date_utils
26 from twisted.words.protocols.jabber import jid 26 from twisted.words.protocols.jabber import jid
27 from twisted.words.protocols.jabber.xmlstream import XMPPHandler 27 from twisted.words.protocols.jabber.xmlstream import XMPPHandler
28 from twisted.internet import defer 28 from twisted.internet import defer
29 from sat.core.log import getLogger 29 from sat.core.log import getLogger
30
30 log = getLogger(__name__) 31 log = getLogger(__name__)
31 from wokkel import disco, iwokkel 32 from wokkel import disco, iwokkel
32 from wokkel import data_form 33 from wokkel import data_form
33 from wokkel import generic 34 from wokkel import generic
34 from zope.interface import implements 35 from zope.interface import implements
35 from collections import Iterable 36 from collections import Iterable
36 import copy 37 import copy
37 import itertools 38 import itertools
38 39
39 NS_SCHEMA = 'https://salut-a-toi/protocol/schema:0' 40 NS_SCHEMA = "https://salut-a-toi/protocol/schema:0"
40 41
41 PLUGIN_INFO = { 42 PLUGIN_INFO = {
42 C.PI_NAME: "PubSub Schema", 43 C.PI_NAME: "PubSub Schema",
43 C.PI_IMPORT_NAME: "PUBSUB_SCHEMA", 44 C.PI_IMPORT_NAME: "PUBSUB_SCHEMA",
44 C.PI_TYPE: "EXP", 45 C.PI_TYPE: "EXP",
45 C.PI_PROTOCOLS: [], 46 C.PI_PROTOCOLS: [],
46 C.PI_DEPENDENCIES: ["XEP-0060", "IDENTITY"], 47 C.PI_DEPENDENCIES: ["XEP-0060", "IDENTITY"],
47 C.PI_MAIN: "PubsubSchema", 48 C.PI_MAIN: "PubsubSchema",
48 C.PI_HANDLER: "yes", 49 C.PI_HANDLER: "yes",
49 C.PI_DESCRIPTION: _("""Handle Pubsub data schemas""") 50 C.PI_DESCRIPTION: _("""Handle Pubsub data schemas"""),
50 } 51 }
51 52
52 53
53 class PubsubSchema(object): 54 class PubsubSchema(object):
54
55 def __init__(self, host): 55 def __init__(self, host):
56 log.info(_(u"PubSub Schema initialization")) 56 log.info(_(u"PubSub Schema initialization"))
57 self.host = host 57 self.host = host
58 self._p = self.host.plugins["XEP-0060"] 58 self._p = self.host.plugins["XEP-0060"]
59 self._i = self.host.plugins["IDENTITY"] 59 self._i = self.host.plugins["IDENTITY"]
60 host.bridge.addMethod("psSchemaGet", ".plugin", 60 host.bridge.addMethod(
61 in_sign='sss', out_sign='s', 61 "psSchemaGet",
62 method=self._getSchema, 62 ".plugin",
63 async=True 63 in_sign="sss",
64 ) 64 out_sign="s",
65 host.bridge.addMethod("psSchemaSet", ".plugin", 65 method=self._getSchema,
66 in_sign='ssss', out_sign='', 66 async=True,
67 method=self._setSchema, 67 )
68 async=True 68 host.bridge.addMethod(
69 ) 69 "psSchemaSet",
70 host.bridge.addMethod("psSchemaUIGet", ".plugin", 70 ".plugin",
71 in_sign='sss', out_sign='s', 71 in_sign="ssss",
72 method=utils.partial(self._getUISchema, default_node=None), 72 out_sign="",
73 async=True 73 method=self._setSchema,
74 ) 74 async=True,
75 host.bridge.addMethod("psItemsFormGet", ".plugin", 75 )
76 in_sign='ssssiassa{ss}s', out_sign='(asa{ss})', 76 host.bridge.addMethod(
77 method=self._getDataFormItems, 77 "psSchemaUIGet",
78 async=True) 78 ".plugin",
79 host.bridge.addMethod("psItemFormSend", ".plugin", 79 in_sign="sss",
80 in_sign='ssa{sas}ssa{ss}s', out_sign='s', 80 out_sign="s",
81 method=self._sendDataFormItem, 81 method=utils.partial(self._getUISchema, default_node=None),
82 async=True) 82 async=True,
83 )
84 host.bridge.addMethod(
85 "psItemsFormGet",
86 ".plugin",
87 in_sign="ssssiassa{ss}s",
88 out_sign="(asa{ss})",
89 method=self._getDataFormItems,
90 async=True,
91 )
92 host.bridge.addMethod(
93 "psItemFormSend",
94 ".plugin",
95 in_sign="ssa{sas}ssa{ss}s",
96 out_sign="s",
97 method=self._sendDataFormItem,
98 async=True,
99 )
83 100
84 def getHandler(self, client): 101 def getHandler(self, client):
85 return SchemaHandler() 102 return SchemaHandler()
86 103
87 def _getSchemaBridgeCb(self, schema_elt): 104 def _getSchemaBridgeCb(self, schema_elt):
88 if schema_elt is None: 105 if schema_elt is None:
89 return u'' 106 return u""
90 return schema_elt.toXml() 107 return schema_elt.toXml()
91 108
92 def _getSchema(self, service, nodeIdentifier, profile_key=C.PROF_KEY_NONE): 109 def _getSchema(self, service, nodeIdentifier, profile_key=C.PROF_KEY_NONE):
93 client = self.host.getClient(profile_key) 110 client = self.host.getClient(profile_key)
94 service = None if not service else jid.JID(service) 111 service = None if not service else jid.JID(service)
96 d.addCallback(self._getSchemaBridgeCb) 113 d.addCallback(self._getSchemaBridgeCb)
97 return d 114 return d
98 115
99 def _getSchemaCb(self, iq_elt): 116 def _getSchemaCb(self, iq_elt):
100 try: 117 try:
101 schema_elt = next(iq_elt.elements(NS_SCHEMA, 'schema')) 118 schema_elt = next(iq_elt.elements(NS_SCHEMA, "schema"))
102 except StopIteration: 119 except StopIteration:
103 raise exceptions.DataError('missing <schema> element') 120 raise exceptions.DataError("missing <schema> element")
104 try: 121 try:
105 x_elt = next(schema_elt.elements((data_form.NS_X_DATA, 'x'))) 122 x_elt = next(schema_elt.elements((data_form.NS_X_DATA, "x")))
106 except StopIteration: 123 except StopIteration:
107 # there is not schema on this node 124 # there is not schema on this node
108 return None 125 return None
109 return x_elt 126 return x_elt
110 127
115 None to use our PEP 132 None to use our PEP
116 @param nodeIdentifier(unicode): node to get schema from 133 @param nodeIdentifier(unicode): node to get schema from
117 @return (domish.Element, None): schema (<x> element) 134 @return (domish.Element, None): schema (<x> element)
118 None if not schema has been set on this node 135 None if not schema has been set on this node
119 """ 136 """
120 iq_elt = client.IQ(u'get') 137 iq_elt = client.IQ(u"get")
121 if service is not None: 138 if service is not None:
122 iq_elt['to'] = service.full() 139 iq_elt["to"] = service.full()
123 pubsub_elt = iq_elt.addElement((NS_SCHEMA, 'pubsub')) 140 pubsub_elt = iq_elt.addElement((NS_SCHEMA, "pubsub"))
124 schema_elt = pubsub_elt.addElement((NS_SCHEMA, 'schema')) 141 schema_elt = pubsub_elt.addElement((NS_SCHEMA, "schema"))
125 schema_elt['node'] = nodeIdentifier 142 schema_elt["node"] = nodeIdentifier
126 d = iq_elt.send() 143 d = iq_elt.send()
127 d.addCallback(self._getSchemaCb) 144 d.addCallback(self._getSchemaCb)
128 return d 145 return d
129 146
130 @defer.inlineCallbacks 147 @defer.inlineCallbacks
131 def getSchemaForm(self, client, service, nodeIdentifier, schema=None, form_type='form', copy_form=True): 148 def getSchemaForm(
149 self,
150 client,
151 service,
152 nodeIdentifier,
153 schema=None,
154 form_type="form",
155 copy_form=True,
156 ):
132 """get data form from node's schema 157 """get data form from node's schema
133 158
134 @param service(None, jid.JID): PubSub service 159 @param service(None, jid.JID): PubSub service
135 @param nodeIdentifier(unicode): node 160 @param nodeIdentifier(unicode): node
136 @param schema(domish.Element, data_form.Form, None): node schema 161 @param schema(domish.Element, data_form.Form, None): node schema
145 """ 170 """
146 if schema is None: 171 if schema is None:
147 log.debug(_(u"unspecified schema, we need to request it")) 172 log.debug(_(u"unspecified schema, we need to request it"))
148 schema = yield self.getSchema(client, service, nodeIdentifier) 173 schema = yield self.getSchema(client, service, nodeIdentifier)
149 if schema is None: 174 if schema is None:
150 raise exceptions.DataError(_(u"no schema specified, and this node has no schema either, we can't construct the data form")) 175 raise exceptions.DataError(
176 _(
177 u"no schema specified, and this node has no schema either, we can't construct the data form"
178 )
179 )
151 elif isinstance(schema, data_form.Form): 180 elif isinstance(schema, data_form.Form):
152 if copy_form: 181 if copy_form:
153 schema = copy.deepcopy(schema) 182 schema = copy.deepcopy(schema)
154 defer.returnValue(schema) 183 defer.returnValue(schema)
155 184
156 try: 185 try:
157 form = data_form.Form.fromElement(schema) 186 form = data_form.Form.fromElement(schema)
158 except data_form.Error as e: 187 except data_form.Error as e:
159 raise exceptions.DataError(_(u"Invalid Schema: {msg}").format( 188 raise exceptions.DataError(_(u"Invalid Schema: {msg}").format(msg=e))
160 msg = e))
161 form.formType = form_type 189 form.formType = form_type
162 defer.returnValue(form) 190 defer.returnValue(form)
163 191
164 def schema2XMLUI(self, schema_elt): 192 def schema2XMLUI(self, schema_elt):
165 form = data_form.Form.fromElement(schema_elt) 193 form = data_form.Form.fromElement(schema_elt)
166 xmlui = xml_tools.dataForm2XMLUI(form, '') 194 xmlui = xml_tools.dataForm2XMLUI(form, "")
167 return xmlui 195 return xmlui
168 196
169 def _getUISchema(self, service, nodeIdentifier, default_node=None, profile_key=C.PROF_KEY_NONE): 197 def _getUISchema(
198 self, service, nodeIdentifier, default_node=None, profile_key=C.PROF_KEY_NONE
199 ):
170 if not nodeIdentifier: 200 if not nodeIdentifier:
171 if not default_node: 201 if not default_node:
172 raise ValueError(_(u"nodeIndentifier needs to be set")) 202 raise ValueError(_(u"nodeIndentifier needs to be set"))
173 nodeIdentifier = default_node 203 nodeIdentifier = default_node
174 client = self.host.getClient(profile_key) 204 client = self.host.getClient(profile_key)
183 return d 213 return d
184 214
185 def _setSchema(self, service, nodeIdentifier, schema, profile_key=C.PROF_KEY_NONE): 215 def _setSchema(self, service, nodeIdentifier, schema, profile_key=C.PROF_KEY_NONE):
186 client = self.host.getClient(profile_key) 216 client = self.host.getClient(profile_key)
187 service = None if not service else jid.JID(service) 217 service = None if not service else jid.JID(service)
188 schema = generic.parseXml(schema.encode('utf-8')) 218 schema = generic.parseXml(schema.encode("utf-8"))
189 return self.setSchema(client, service, nodeIdentifier, schema) 219 return self.setSchema(client, service, nodeIdentifier, schema)
190 220
191 def setSchema(self, client, service, nodeIdentifier, schema): 221 def setSchema(self, client, service, nodeIdentifier, schema):
192 """set or replace PubSub node schema 222 """set or replace PubSub node schema
193 223
194 @param schema(domish.Element, None): schema to set 224 @param schema(domish.Element, None): schema to set
195 None if schema need to be removed 225 None if schema need to be removed
196 """ 226 """
197 iq_elt = client.IQ() 227 iq_elt = client.IQ()
198 if service is not None: 228 if service is not None:
199 iq_elt['to'] = service.full() 229 iq_elt["to"] = service.full()
200 pubsub_elt = iq_elt.addElement((NS_SCHEMA, 'pubsub')) 230 pubsub_elt = iq_elt.addElement((NS_SCHEMA, "pubsub"))
201 schema_elt = pubsub_elt.addElement((NS_SCHEMA, 'schema')) 231 schema_elt = pubsub_elt.addElement((NS_SCHEMA, "schema"))
202 schema_elt['node'] = nodeIdentifier 232 schema_elt["node"] = nodeIdentifier
203 if schema is not None: 233 if schema is not None:
204 schema_elt.addChild(schema) 234 schema_elt.addChild(schema)
205 return iq_elt.send() 235 return iq_elt.send()
206 236
207 def _getDataFormItems(self, form_ns='', service='', node='', schema='', max_items=10, item_ids=None, sub_id=None, extra_dict=None, profile_key=C.PROF_KEY_NONE): 237 def _getDataFormItems(
238 self,
239 form_ns="",
240 service="",
241 node="",
242 schema="",
243 max_items=10,
244 item_ids=None,
245 sub_id=None,
246 extra_dict=None,
247 profile_key=C.PROF_KEY_NONE,
248 ):
208 client = self.host.getClient(profile_key) 249 client = self.host.getClient(profile_key)
209 service = jid.JID(service) if service else None 250 service = jid.JID(service) if service else None
210 if not node: 251 if not node:
211 raise exceptions.DataError(_(u'empty node is not allowed')) 252 raise exceptions.DataError(_(u"empty node is not allowed"))
212 if schema: 253 if schema:
213 schema = generic.parseXml(schema.encode('utf-8')) 254 schema = generic.parseXml(schema.encode("utf-8"))
214 else: 255 else:
215 schema = None 256 schema = None
216 max_items = None if max_items == C.NO_LIMIT else max_items 257 max_items = None if max_items == C.NO_LIMIT else max_items
217 extra = self._p.parseExtra(extra_dict) 258 extra = self._p.parseExtra(extra_dict)
218 d = self.getDataFormItems(client, service, node, schema, max_items or None, item_ids, sub_id or None, extra.rsm_request, extra.extra, form_ns=form_ns or None) 259 d = self.getDataFormItems(
260 client,
261 service,
262 node,
263 schema,
264 max_items or None,
265 item_ids,
266 sub_id or None,
267 extra.rsm_request,
268 extra.extra,
269 form_ns=form_ns or None,
270 )
219 d.addCallback(self._p.serItemsData) 271 d.addCallback(self._p.serItemsData)
220 return d 272 return d
221 273
222 @defer.inlineCallbacks 274 @defer.inlineCallbacks
223 def getDataFormItems(self, client, service, nodeIdentifier, schema=None, max_items=None, item_ids=None, sub_id=None, rsm_request=None, extra=None, default_node=None, form_ns=None, filters=None): 275 def getDataFormItems(
276 self,
277 client,
278 service,
279 nodeIdentifier,
280 schema=None,
281 max_items=None,
282 item_ids=None,
283 sub_id=None,
284 rsm_request=None,
285 extra=None,
286 default_node=None,
287 form_ns=None,
288 filters=None,
289 ):
224 """Get items known as being data forms, and convert them to XMLUI 290 """Get items known as being data forms, and convert them to XMLUI
225 291
226 @param schema(domish.Element, data_form.Form, None): schema of the node if known 292 @param schema(domish.Element, data_form.Form, None): schema of the node if known
227 if None, it will be retrieved from node 293 if None, it will be retrieved from node
228 @param default_node(unicode): node to use if nodeIdentifier is None or empty 294 @param default_node(unicode): node to use if nodeIdentifier is None or empty
235 it will be skipped 301 it will be skipped
236 @raise ValueError: one argument is invalid 302 @raise ValueError: one argument is invalid
237 """ 303 """
238 if not nodeIdentifier: 304 if not nodeIdentifier:
239 if not default_node: 305 if not default_node:
240 raise ValueError(_(u"default_node must be set if nodeIdentifier is not set")) 306 raise ValueError(
307 _(u"default_node must be set if nodeIdentifier is not set")
308 )
241 nodeIdentifier = default_node 309 nodeIdentifier = default_node
242 # we need the initial form to get options of fields when suitable 310 # we need the initial form to get options of fields when suitable
243 schema_form = yield self.getSchemaForm(client, service, nodeIdentifier, schema, form_type='result', copy_form=False) 311 schema_form = yield self.getSchemaForm(
244 items_data = yield self._p.getItems(client, service, nodeIdentifier, max_items, item_ids, sub_id, rsm_request, extra) 312 client, service, nodeIdentifier, schema, form_type="result", copy_form=False
313 )
314 items_data = yield self._p.getItems(
315 client,
316 service,
317 nodeIdentifier,
318 max_items,
319 item_ids,
320 sub_id,
321 rsm_request,
322 extra,
323 )
245 items, metadata = items_data 324 items, metadata = items_data
246 items_xmlui = [] 325 items_xmlui = []
247 for item_elt in items: 326 for item_elt in items:
248 for x_elt in item_elt.elements((data_form.NS_X_DATA, u'x')): 327 for x_elt in item_elt.elements((data_form.NS_X_DATA, u"x")):
249 form = data_form.Form.fromElement(x_elt) 328 form = data_form.Form.fromElement(x_elt)
250 if form_ns and form.formNamespace != form_ns: 329 if form_ns and form.formNamespace != form_ns:
251 continue 330 continue
252 xmlui = xml_tools.dataFormResult2XMLUI( 331 xmlui = xml_tools.dataFormResult2XMLUI(
253 form, 332 form,
254 schema_form, 333 schema_form,
255 # FIXME: conflicts with schema (i.e. if "id" or "publisher" already exists) 334 # FIXME: conflicts with schema (i.e. if "id" or "publisher" already exists)
256 # are not checked 335 # are not checked
257 prepend = (('label', 'id'),('text', item_elt['id'], u'id'), 336 prepend=(
258 ('label', 'publisher'),('text', item_elt.getAttribute('publisher',''), u'publisher')), 337 ("label", "id"),
259 filters = filters, 338 ("text", item_elt["id"], u"id"),
260 ) 339 ("label", "publisher"),
340 ("text", item_elt.getAttribute("publisher", ""), u"publisher"),
341 ),
342 filters=filters,
343 )
261 items_xmlui.append(xmlui) 344 items_xmlui.append(xmlui)
262 break 345 break
263 defer.returnValue((items_xmlui, metadata)) 346 defer.returnValue((items_xmlui, metadata))
264 347
265 348 def _sendDataFormItem(
266 def _sendDataFormItem(self, service, nodeIdentifier, values, schema=None, item_id=None, extra=None, profile_key=C.PROF_KEY_NONE): 349 self,
350 service,
351 nodeIdentifier,
352 values,
353 schema=None,
354 item_id=None,
355 extra=None,
356 profile_key=C.PROF_KEY_NONE,
357 ):
267 client = self.host.getClient(profile_key) 358 client = self.host.getClient(profile_key)
268 service = None if not service else jid.JID(service) 359 service = None if not service else jid.JID(service)
269 if schema: 360 if schema:
270 schema = generic.parseXml(schema.encode('utf-8')) 361 schema = generic.parseXml(schema.encode("utf-8"))
271 else: 362 else:
272 schema = None 363 schema = None
273 d = self.sendDataFormItem(client, service, nodeIdentifier, values, schema, item_id or None, extra, deserialise=True) 364 d = self.sendDataFormItem(
274 d.addCallback(lambda ret: ret or u'') 365 client,
366 service,
367 nodeIdentifier,
368 values,
369 schema,
370 item_id or None,
371 extra,
372 deserialise=True,
373 )
374 d.addCallback(lambda ret: ret or u"")
275 return d 375 return d
276 376
277 @defer.inlineCallbacks 377 @defer.inlineCallbacks
278 def sendDataFormItem(self, client, service, nodeIdentifier, values, schema=None, item_id=None, extra=None, deserialise=False): 378 def sendDataFormItem(
379 self,
380 client,
381 service,
382 nodeIdentifier,
383 values,
384 schema=None,
385 item_id=None,
386 extra=None,
387 deserialise=False,
388 ):
279 """Publish an item as a dataform when we know that there is a schema 389 """Publish an item as a dataform when we know that there is a schema
280 390
281 @param values(dict[key(unicode), [iterable[object], object]]): values set for the form 391 @param values(dict[key(unicode), [iterable[object], object]]): values set for the form
282 if not iterable, will be put in a list 392 if not iterable, will be put in a list
283 @param schema(domish.Element, data_form.Form, None): data schema 393 @param schema(domish.Element, data_form.Form, None): data schema
287 This is done in this method and not directly in _sendDataFormItem because we need to know the data type 397 This is done in this method and not directly in _sendDataFormItem because we need to know the data type
288 which is in the form, not availablable in _sendDataFormItem 398 which is in the form, not availablable in _sendDataFormItem
289 other parameters as the same as for [self._p.sendItem] 399 other parameters as the same as for [self._p.sendItem]
290 @return (unicode): id of the created item 400 @return (unicode): id of the created item
291 """ 401 """
292 form = yield self.getSchemaForm(client, service, nodeIdentifier, schema, form_type='submit') 402 form = yield self.getSchemaForm(
403 client, service, nodeIdentifier, schema, form_type="submit"
404 )
293 405
294 for name, values_list in values.iteritems(): 406 for name, values_list in values.iteritems():
295 try: 407 try:
296 field = form.fields[name] 408 field = form.fields[name]
297 except KeyError: 409 except KeyError:
298 log.warning(_(u"field {name} doesn't exist, ignoring it").format(name=name)) 410 log.warning(
411 _(u"field {name} doesn't exist, ignoring it").format(name=name)
412 )
299 continue 413 continue
300 if isinstance(values_list, basestring) or not isinstance(values_list, Iterable): 414 if isinstance(values_list, basestring) or not isinstance(
415 values_list, Iterable
416 ):
301 values_list = [values_list] 417 values_list = [values_list]
302 if deserialise: 418 if deserialise:
303 if field.fieldType == 'boolean': 419 if field.fieldType == "boolean":
304 values_list = [C.bool(v) for v in values_list] 420 values_list = [C.bool(v) for v in values_list]
305 elif field.fieldType == 'text-multi': 421 elif field.fieldType == "text-multi":
306 # for text-multi, lines must be put on separate values 422 # for text-multi, lines must be put on separate values
307 values_list = list(itertools.chain(*[v.splitlines() for v in values_list])) 423 values_list = list(
308 424 itertools.chain(*[v.splitlines() for v in values_list])
309 elif 'jid' in field.fieldType: 425 )
426
427 elif "jid" in field.fieldType:
310 values_list = [jid.JID(v) for v in values_list] 428 values_list = [jid.JID(v) for v in values_list]
311 if 'list' in field.fieldType: 429 if "list" in field.fieldType:
312 # for lists, we check that given values are allowed in form 430 # for lists, we check that given values are allowed in form
313 allowed_values = [o.value for o in field.options] 431 allowed_values = [o.value for o in field.options]
314 values_list = [v for v in values_list if v in allowed_values] 432 values_list = [v for v in values_list if v in allowed_values]
315 if not values_list: 433 if not values_list:
316 # if values don't map to allowed values, we use default ones 434 # if values don't map to allowed values, we use default ones
317 values_list = field.values 435 values_list = field.values
318 field.values = values_list 436 field.values = values_list
319 437
320 yield self._p.sendItem(client, service, nodeIdentifier, form.toElement(), item_id, extra) 438 yield self._p.sendItem(
439 client, service, nodeIdentifier, form.toElement(), item_id, extra
440 )
321 441
322 ## filters ## 442 ## filters ##
323 # filters useful for data form to XMLUI conversion # 443 # filters useful for data form to XMLUI conversion #
324 444
325 def valueOrPublisherFilter(self, form_xmlui, widget_type, args, kwargs): 445 def valueOrPublisherFilter(self, form_xmlui, widget_type, args, kwargs):
326 """Replace missing value by publisher's user part""" 446 """Replace missing value by publisher's user part"""
327 if not args[0]: 447 if not args[0]:
328 # value is not filled: we use user part of publisher (if we have it) 448 # value is not filled: we use user part of publisher (if we have it)
329 try: 449 try:
330 publisher = jid.JID(form_xmlui.named_widgets['publisher'].value) 450 publisher = jid.JID(form_xmlui.named_widgets["publisher"].value)
331 except (KeyError, RuntimeError): 451 except (KeyError, RuntimeError):
332 pass 452 pass
333 else: 453 else:
334 args[0] = publisher.user.capitalize() 454 args[0] = publisher.user.capitalize()
335 return widget_type, args, kwargs 455 return widget_type, args, kwargs
337 def textbox2ListFilter(self, form_xmlui, widget_type, args, kwargs): 457 def textbox2ListFilter(self, form_xmlui, widget_type, args, kwargs):
338 """Split lines of a textbox in a list 458 """Split lines of a textbox in a list
339 459
340 main use case is using a textbox for labels 460 main use case is using a textbox for labels
341 """ 461 """
342 if widget_type != u'textbox': 462 if widget_type != u"textbox":
343 return widget_type, args, kwargs 463 return widget_type, args, kwargs
344 widget_type = u'list' 464 widget_type = u"list"
345 options = [o for o in args.pop(0).split(u'\n') if o] 465 options = [o for o in args.pop(0).split(u"\n") if o]
346 kwargs = {'options': options, 466 kwargs = {
347 'name': kwargs.get('name'), 467 "options": options,
348 'styles': (u'noselect', u'extensible', u'reducible')} 468 "name": kwargs.get("name"),
469 "styles": (u"noselect", u"extensible", u"reducible"),
470 }
349 return widget_type, args, kwargs 471 return widget_type, args, kwargs
350 472
351 def dateFilter(self, form_xmlui, widget_type, args, kwargs): 473 def dateFilter(self, form_xmlui, widget_type, args, kwargs):
352 """Convert a string with a date to a unix timestamp""" 474 """Convert a string with a date to a unix timestamp"""
353 if widget_type != u'string' or not args[0]: 475 if widget_type != u"string" or not args[0]:
354 return widget_type, args, kwargs 476 return widget_type, args, kwargs
355 # we convert XMPP date to timestamp 477 # we convert XMPP date to timestamp
356 try: 478 try:
357 args[0] = unicode(date_utils.date_parse(args[0])) 479 args[0] = unicode(date_utils.date_parse(args[0]))
358 except Exception as e: 480 except Exception as e:
375 sub_id = None 497 sub_id = None
376 extra = self._p.parseExtra(extra_dict) 498 extra = self._p.parseExtra(extra_dict)
377 499
378 return client, service, node, max_items, extra, sub_id 500 return client, service, node, max_items, extra, sub_id
379 501
380 def _get(self, service='', node='', max_items=10, item_ids=None, sub_id=None, extra=None, default_node=None, form_ns=None, filters=None, profile_key=C.PROF_KEY_NONE): 502 def _get(
503 self,
504 service="",
505 node="",
506 max_items=10,
507 item_ids=None,
508 sub_id=None,
509 extra=None,
510 default_node=None,
511 form_ns=None,
512 filters=None,
513 profile_key=C.PROF_KEY_NONE,
514 ):
381 """Bridge method to retrieve data from node with schema 515 """Bridge method to retrieve data from node with schema
382 516
383 this method is a helper so dependant plugins can use it directly 517 this method is a helper so dependant plugins can use it directly
384 when adding *Get methods 518 when adding *Get methods
385 extra can have the key "labels_as_list" which is a hack to convert 519 extra can have the key "labels_as_list" which is a hack to convert
390 filters = {} 524 filters = {}
391 if extra is None: 525 if extra is None:
392 extra = {} 526 extra = {}
393 # XXX: Q&D way to get list for labels when displaying them, but text when we 527 # XXX: Q&D way to get list for labels when displaying them, but text when we
394 # have to modify them 528 # have to modify them
395 if C.bool(extra.get('labels_as_list', C.BOOL_FALSE)): 529 if C.bool(extra.get("labels_as_list", C.BOOL_FALSE)):
396 filters = filters.copy() 530 filters = filters.copy()
397 filters[u'labels'] = self.textbox2ListFilter 531 filters[u"labels"] = self.textbox2ListFilter
398 client, service, node, max_items, extra, sub_id = self.prepareBridgeGet(service, node, max_items, sub_id, extra, profile_key) 532 client, service, node, max_items, extra, sub_id = self.prepareBridgeGet(
399 d = self.getDataFormItems(client, service, node or None, 533 service, node, max_items, sub_id, extra, profile_key
534 )
535 d = self.getDataFormItems(
536 client,
537 service,
538 node or None,
400 max_items=max_items, 539 max_items=max_items,
401 item_ids=item_ids, 540 item_ids=item_ids,
402 sub_id=sub_id, 541 sub_id=sub_id,
403 rsm_request=extra.rsm_request, 542 rsm_request=extra.rsm_request,
404 extra=extra.extra, 543 extra=extra.extra,
405 default_node=default_node, 544 default_node=default_node,
406 form_ns=form_ns, 545 form_ns=form_ns,
407 filters=filters) 546 filters=filters,
547 )
408 d.addCallback(self._p.serItemsData) 548 d.addCallback(self._p.serItemsData)
409 return d 549 return d
410 550
411 def prepareBridgeSet(self, service, node, schema, item_id, extra, profile_key): 551 def prepareBridgeSet(self, service, node, schema, item_id, extra, profile_key):
412 """Parse arguments received from bridge *Set methods and return higher level data 552 """Parse arguments received from bridge *Set methods and return higher level data
414 @return (tuple): (client, service, node, schema, item_id, extra) usable for internal methods 554 @return (tuple): (client, service, node, schema, item_id, extra) usable for internal methods
415 """ 555 """
416 client = self.host.getClient(profile_key) 556 client = self.host.getClient(profile_key)
417 service = None if not service else jid.JID(service) 557 service = None if not service else jid.JID(service)
418 if schema: 558 if schema:
419 schema = generic.parseXml(schema.encode('utf-8')) 559 schema = generic.parseXml(schema.encode("utf-8"))
420 else: 560 else:
421 schema = None 561 schema = None
422 if extra and u'update' in extra: 562 if extra and u"update" in extra:
423 extra[u'update'] = C.bool(extra[u'update']) 563 extra[u"update"] = C.bool(extra[u"update"])
424 return client, service, node or None, schema, item_id or None, extra 564 return client, service, node or None, schema, item_id or None, extra
425 565
426 def _set(self, service, node, values, schema=None, item_id=None, extra=None, default_node=None, form_ns=None, fill_author=True, profile_key=C.PROF_KEY_NONE): 566 def _set(
567 self,
568 service,
569 node,
570 values,
571 schema=None,
572 item_id=None,
573 extra=None,
574 default_node=None,
575 form_ns=None,
576 fill_author=True,
577 profile_key=C.PROF_KEY_NONE,
578 ):
427 """Bridge method to set item in node with schema 579 """Bridge method to set item in node with schema
428 580
429 this method is a helper so dependant plugins can use it directly 581 this method is a helper so dependant plugins can use it directly
430 when adding *Set methods 582 when adding *Set methods
431 """ 583 """
432 client, service, node, schema, item_id, extra = self.prepareBridgeSet(service, node, schema, item_id, extra) 584 client, service, node, schema, item_id, extra = self.prepareBridgeSet(
433 d = self.set(client, service, node, values, schema, item_id, extra, 585 service, node, schema, item_id, extra
434 deserialise=True, 586 )
435 form_ns=form_ns, 587 d = self.set(
436 default_node=default_node, 588 client,
437 fill_author=fill_author) 589 service,
438 d.addCallback(lambda ret: ret or u'') 590 node,
591 values,
592 schema,
593 item_id,
594 extra,
595 deserialise=True,
596 form_ns=form_ns,
597 default_node=default_node,
598 fill_author=fill_author,
599 )
600 d.addCallback(lambda ret: ret or u"")
439 return d 601 return d
440 602
441 @defer.inlineCallbacks 603 @defer.inlineCallbacks
442 def set(self, client, service, node, values, schema, item_id, extra, deserialise, form_ns, default_node=None, fill_author=True): 604 def set(
605 self,
606 client,
607 service,
608 node,
609 values,
610 schema,
611 item_id,
612 extra,
613 deserialise,
614 form_ns,
615 default_node=None,
616 fill_author=True,
617 ):
443 """Set an item in a node with a schema 618 """Set an item in a node with a schema
444 619
445 This method can be used directly by *Set methods added by dependant plugin 620 This method can be used directly by *Set methods added by dependant plugin
446 @param values(dict[key(unicode), [iterable[object]|object]]): values of the items 621 @param values(dict[key(unicode), [iterable[object]|object]]): values of the items
447 if value is not iterable, it will be put in a list 622 if value is not iterable, it will be put in a list
461 if default_node is None: 636 if default_node is None:
462 raise ValueError(_(u"default_node must be set if node is not set")) 637 raise ValueError(_(u"default_node must be set if node is not set"))
463 node = default_node 638 node = default_node
464 now = utils.xmpp_date() 639 now = utils.xmpp_date()
465 if not item_id: 640 if not item_id:
466 values['created'] = now 641 values["created"] = now
467 elif extra.get(u'update', False): 642 elif extra.get(u"update", False):
468 if item_id is None: 643 if item_id is None:
469 raise exceptions.DataError(_(u'if extra["update"] is set, item_id must be set too')) 644 raise exceptions.DataError(
645 _(u'if extra["update"] is set, item_id must be set too')
646 )
470 try: 647 try:
471 # we get previous item 648 # we get previous item
472 items_data = yield self._p.getItems(client, service, node, item_ids=[item_id]) 649 items_data = yield self._p.getItems(
650 client, service, node, item_ids=[item_id]
651 )
473 item_elt = items_data[0][0] 652 item_elt = items_data[0][0]
474 except Exception as e: 653 except Exception as e:
475 log.warning(_(u"Can't get previous item, update ignored: {reason}").format( 654 log.warning(
476 reason = e)) 655 _(u"Can't get previous item, update ignored: {reason}").format(
656 reason=e
657 )
658 )
477 else: 659 else:
478 # and parse it 660 # and parse it
479 form = data_form.findForm(item_elt, form_ns) 661 form = data_form.findForm(item_elt, form_ns)
480 if form is None: 662 if form is None:
481 log.warning(_(u"Can't parse previous item, update ignored: data form not found").format( 663 log.warning(
482 reason = e)) 664 _(
665 u"Can't parse previous item, update ignored: data form not found"
666 ).format(reason=e)
667 )
483 else: 668 else:
484 for name, field in form.fields.iteritems(): 669 for name, field in form.fields.iteritems():
485 if name not in values: 670 if name not in values:
486 values[name] = u'\n'.join(unicode(v) for v in field.values) 671 values[name] = u"\n".join(unicode(v) for v in field.values)
487 672
488 values['updated'] = now 673 values["updated"] = now
489 if fill_author: 674 if fill_author:
490 if not values.get('author'): 675 if not values.get("author"):
491 identity = yield self._i.getIdentity(client, client.jid) 676 identity = yield self._i.getIdentity(client, client.jid)
492 values['author'] = identity['nick'] 677 values["author"] = identity["nick"]
493 if not values.get('author_jid'): 678 if not values.get("author_jid"):
494 values['author_jid'] = client.jid.full() 679 values["author_jid"] = client.jid.full()
495 item_id = yield self.sendDataFormItem(client, service, node, values, schema, item_id, extra, deserialise) 680 item_id = yield self.sendDataFormItem(
681 client, service, node, values, schema, item_id, extra, deserialise
682 )
496 defer.returnValue(item_id) 683 defer.returnValue(item_id)
497 684
498 685
499 class SchemaHandler(XMPPHandler): 686 class SchemaHandler(XMPPHandler):
500 implements(iwokkel.IDisco) 687 implements(iwokkel.IDisco)
501 688
502 def getDiscoInfo(self, requestor, service, nodeIdentifier=''): 689 def getDiscoInfo(self, requestor, service, nodeIdentifier=""):
503 return [disco.DiscoFeature(NS_SCHEMA)] 690 return [disco.DiscoFeature(NS_SCHEMA)]
504 691
505 def getDiscoItems(self, requestor, service, nodeIdentifier=''): 692 def getDiscoItems(self, requestor, service, nodeIdentifier=""):
506 return [] 693 return []