Mercurial > libervia-backend
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 |