comparison src/plugins/plugin_exp_pubsub_schema.py @ 2371:2268df8c99bf

plugin pubsub schema: values handling: - "schema" attribute can now be specified directly as a data_form.Form (reparsing it will be avoided in this case) - new "deserialise" parameter allows deserialisation from unicode strings in sendDataFormItem - values can now be an iterable or directly the value to use (it will be put in a list automatically in the later case) - "id" is now put directly in XMLUI's "id" field instea of "_id"
author Goffi <goffi@goffi.org>
date Fri, 06 Oct 2017 10:55:51 +0200
parents 41c7717b52cd
children 3704cb959ae8
comparison
equal deleted inserted replaced
2370:2c2b826b0bb3 2371:2268df8c99bf
28 log = getLogger(__name__) 28 log = getLogger(__name__)
29 from wokkel import disco, iwokkel 29 from wokkel import disco, iwokkel
30 from wokkel import data_form 30 from wokkel import data_form
31 from wokkel import generic 31 from wokkel import generic
32 from zope.interface import implements 32 from zope.interface import implements
33 from collections import Iterable
33 34
34 NS_SCHEMA = 'https://salut-a-toi/protocol/schema:0' 35 NS_SCHEMA = 'https://salut-a-toi/protocol/schema:0'
35 NS_SCHEMA_FORM = 'https://salut-a-toi/protocol/schema#schema:0' 36 NS_SCHEMA_FORM = 'https://salut-a-toi/protocol/schema#schema:0'
36 37
37 PLUGIN_INFO = { 38 PLUGIN_INFO = {
128 def getSchemaForm(self, client, service, nodeIdentifier, schema=None, form_type='form'): 129 def getSchemaForm(self, client, service, nodeIdentifier, schema=None, form_type='form'):
129 """get data form from node's schema 130 """get data form from node's schema
130 131
131 @param service(None, jid.JID): PubSub service 132 @param service(None, jid.JID): PubSub service
132 @param nodeIdentifier(unicode): node 133 @param nodeIdentifier(unicode): node
133 @param schema(domish.Element, None): node schema 134 @param schema(domish.Element, data_form.Form, None): node schema
135 if domish.Element, will be converted to data form
136 if data_form.Form it will be returned without modification
134 if None, it will be retrieved from node (imply one additional XMPP request) 137 if None, it will be retrieved from node (imply one additional XMPP request)
135 @return(data_form.Form): data form 138 @return(data_form.Form): data form
136 """ 139 """
137 if schema is None: 140 if schema is None:
138 log.debug(_(u"unspecified schema, we need to request it")) 141 log.debug(_(u"unspecified schema, we need to request it"))
139 schema = yield self.getSchema(client, service, nodeIdentifier) 142 schema = yield self.getSchema(client, service, nodeIdentifier)
140 if schema is None: 143 if schema is None:
141 raise exceptions.DataError(_(u"no schema specified, and this node has no schema either, we can't construct the data form")) 144 raise exceptions.DataError(_(u"no schema specified, and this node has no schema either, we can't construct the data form"))
145 elif isinstance(schema, data_form.Form):
146 defer.returnValue(schema)
142 147
143 try: 148 try:
144 form = data_form.Form.fromElement(schema) 149 form = data_form.Form.fromElement(schema)
145 except data_form.Error as e: 150 except data_form.Error as e:
146 raise exceptions.DataError(_(u"Invalid Schema: {msg}").format( 151 raise exceptions.DataError(_(u"Invalid Schema: {msg}").format(
204 def getDataFormItems(self, client, form_ns, service, nodeIdentifier, schema=None, max_items=None, item_ids=None, sub_id=None, rsm_request=None, extra=None): 209 def getDataFormItems(self, client, form_ns, service, nodeIdentifier, schema=None, max_items=None, item_ids=None, sub_id=None, rsm_request=None, extra=None):
205 """Get items known as being data forms, and convert them to XMLUI 210 """Get items known as being data forms, and convert them to XMLUI
206 211
207 @param form_ns (unicode, None): namespace of the form 212 @param form_ns (unicode, None): namespace of the form
208 None to accept everything, even if form has no namespace 213 None to accept everything, even if form has no namespace
209 @param schema(domish.Element, None): schema of the node if known 214 @param schema(domish.Element, data_form.Form, None): schema of the node if known
210 if None, it will be retrieved from node 215 if None, it will be retrieved from node
211 other parameters as the same as for [getItems] 216 other parameters as the same as for [getItems]
212 @return (list[unicode]): XMLUI of the forms 217 @return (list[unicode]): XMLUI of the forms
213 if an item is invalid (not corresponding to form_ns or not a data_form) 218 if an item is invalid (not corresponding to form_ns or not a data_form)
214 it will be skipped 219 it will be skipped
223 form = data_form.Form.fromElement(x_elt) 228 form = data_form.Form.fromElement(x_elt)
224 if form_ns and form.formNamespace != form_ns: 229 if form_ns and form.formNamespace != form_ns:
225 continue 230 continue
226 xmlui = xml_tools.dataFormResult2XMLUI(form, schema_form) 231 xmlui = xml_tools.dataFormResult2XMLUI(form, schema_form)
227 xmlui.addLabel('id') 232 xmlui.addLabel('id')
228 xmlui.addText(item_elt['id'], name='_id') 233 xmlui.addText(item_elt['id'], name='id')
229 items_xmlui.append(xmlui) 234 items_xmlui.append(xmlui)
230 break 235 break
231 defer.returnValue((items_xmlui, metadata)) 236 defer.returnValue((items_xmlui, metadata))
232 237
233 238
236 service = None if not service else jid.JID(service) 241 service = None if not service else jid.JID(service)
237 if schema: 242 if schema:
238 schema = generic.parseXml(schema.encode('utf-8')) 243 schema = generic.parseXml(schema.encode('utf-8'))
239 else: 244 else:
240 schema = None 245 schema = None
241 d = self.sendDataFormItem(client, service, nodeIdentifier, values, schema, item_id or None, extra) 246 d = self.sendDataFormItem(client, service, nodeIdentifier, values, schema, True, item_id or None, extra)
242 d.addCallback(lambda ret: ret or u'') 247 d.addCallback(lambda ret: ret or u'')
243 return d 248 return d
244 249
245 @defer.inlineCallbacks 250 @defer.inlineCallbacks
246 def sendDataFormItem(self, client, service, nodeIdentifier, values, schema=None, item_id=None, extra=None): 251 def sendDataFormItem(self, client, service, nodeIdentifier, values, schema=None, deserialise=False, item_id=None, extra=None):
247 """Publish an item as a dataform when we know that there is a schema 252 """Publish an item as a dataform when we know that there is a schema
248 253
249 @param values(dict[unicode, list[unicode]]): values set for the form 254 @param values(dict[[iterable[object], object]): values set for the form
250 @param schema(unicode, None): data schema 255 if not iterable, will be put in a list
256 @param schema(domish.Element, data_form.Form, None): data schema
251 None to retrieve data schema from node (need to do a additional XMPP call) 257 None to retrieve data schema from node (need to do a additional XMPP call)
252 Schema is need to construct data form to publish 258 Schema is needed to construct data form to publish
259 @param deserialise(bool): if True, data are list of unicode and must be deserialized according to expected type
260 This is done in this method and not directly in _sendDataFormItem because we need to know the data type
261 which is in the form, not availablable in _sendDataFormItem
253 other parameters as the same as for [self._p.sendItem] 262 other parameters as the same as for [self._p.sendItem]
254 """ 263 """
255 form = yield self.getSchemaForm(client, service, nodeIdentifier, schema, form_type='submit') 264 form = yield self.getSchemaForm(client, service, nodeIdentifier, schema, form_type='submit')
256 265
257 for name, values_list in values.iteritems(): 266 for name, values_list in values.iteritems():
258 try: 267 try:
259 field = form.fields[name] 268 field = form.fields[name]
260 except KeyError: 269 except KeyError:
261 log.warning(_(u"field {name} doesn't exist, ignoring it").format(name=name)) 270 log.warning(_(u"field {name} doesn't exist, ignoring it").format(name=name))
262 continue 271 continue
263 if field.fieldType == 'boolean': 272 if isinstance(values_list, basestring) or not isinstance(values_list, Iterable):
264 values_list = [C.bool(v) for v in values_list] 273 values_list = [values_list]
265 elif 'jid' in field.fieldType: 274 if deserialise:
266 values_list = [jid.JID(v) for v in values_list] 275 if field.fieldType == 'boolean':
276 values_list = [C.bool(v) for v in values_list]
277 elif 'jid' in field.fieldType:
278 values_list = [jid.JID(v) for v in values_list]
267 field.values = values_list 279 field.values = values_list
268 280
269 yield self._p.sendItem(client, service, nodeIdentifier, form.toElement(), item_id, extra) 281 yield self._p.sendItem(client, service, nodeIdentifier, form.toElement(), item_id, extra)
270 282
271 283