diff src/plugins/plugin_xep_0020.py @ 1577:d04d7402b8e9

plugins XEP-0020, XEP-0065, XEP-0095, XEP-0096: fixed file copy with Stream Initiation: /!\ range is not working yet /!\ pipe plugin is broken for now
author Goffi <goffi@goffi.org>
date Wed, 11 Nov 2015 18:19:49 +0100
parents 3265a2639182
children 14fcbaa82fd4
line wrap: on
line diff
--- a/src/plugins/plugin_xep_0020.py	Wed Nov 11 18:19:49 2015 +0100
+++ b/src/plugins/plugin_xep_0020.py	Wed Nov 11 18:19:49 2015 +0100
@@ -20,7 +20,7 @@
 from sat.core.i18n import _
 from sat.core.log import getLogger
 log = getLogger(__name__)
-from twisted.words.protocols.jabber import client, jid
+from core import exceptions
 from twisted.words.xish import domish
 
 from zope.interface import implements
@@ -55,53 +55,93 @@
 
     def getFeatureElt(self, elt):
         """Check element's children to find feature elements
-        @param elt: domish.Element
-        @return: feature elements"""
-        return [child for child in elt.elements() if child.name == 'feature']
+
+        @param elt(domish.Element): parent element of the feature element
+        @return: feature elements
+        @raise exceptions.NotFound: no feature element found
+        """
+        try:
+            feature_elt = elt.elements(NS_FEATURE_NEG, 'feature').next()
+        except StopIteration:
+            raise exceptions.NotFound
+        return feature_elt
+
+    def _getForm(self, elt, namespace):
+        """Return the first child data form
 
-    def getChoosedOptions(self, elt):
+        @param elt(domish.Element): parent of the data form
+        @param namespace (None, unicode): form namespace or None to ignore
+        @return (None, data_form.Form): data form or None is nothing is found
+        """
+        if namespace is None:
+            try:
+                form_elt = elt.elements(data_form.NS_X_DATA).next()
+            except StopIteration:
+                return None
+            else:
+                return data_form.Form.fromElement(form_elt)
+        else:
+            return data_form.findForm(elt, namespace)
+
+    def getChoosedOptions(self, feature_elt, namespace):
         """Return choosed feature for feature element
-        @param elt: feature domish element
-        @return: dict with feature name as key, and choosed option as value"""
-        form = data_form.Form.fromElement(elt.firstChildElement())
+
+        @param feature_elt(domish.Element): feature domish element
+        @param namespace (None, unicode): form namespace or None to ignore
+        @return (dict): feature name as key, and choosed option as value
+        @raise exceptions.NotFound: not data form is found
+        """
+        form = self._getForm(feature_elt, namespace)
+        if form is None:
+            raise exceptions.NotFound
         result = {}
         for field in form.fields:
             values = form.fields[field].values
             result[field] = values[0] if values else None
             if len(values) > 1:
-                log.warning(_(u"More than one value choosed for %s, keeping the first one") % field)
+                log.warning(_(u"More than one value choosed for {}, keeping the first one").format(field))
         return result
 
-    def negociate(self, feature_elt, form_type, negociable_values):
-        """Negociate the feature options
-        @param feature_elt: feature domish element
-        @param form_type: the option to negociate
-        @param negociable_values: acceptable values for this negociation"""
-        form = data_form.Form.fromElement(feature_elt.firstChildElement())
-        options = [option.value for option in form.fields[form_type].options]
-        for value in negociable_values:
+    def negotiate(self, feature_elt, name, negotiable_values, namespace):
+        """Negotiate the feature options
+
+        @param feature_elt(domish.Element): feature element
+        @param name: the option name (i.e. field's var attribute) to negotiate
+        @param negotiable_values(iterable): acceptable values for this negotiation
+            first corresponding value will be returned
+        @param namespace (None, unicode): form namespace or None to ignore
+        @raise KeyError: name is not found in data form fields
+        """
+        form = self._getForm(feature_elt, namespace)
+        options = [option.value for option in form.fields[name].options]
+        for value in negotiable_values:
             if value in options:
                 return value
         return None
 
-    def chooseOption(self, options_dict):
+    def chooseOption(self, options, namespace):
         """Build a feature element with choosed options
-        @param options_dict: dict with feature as key and choosed option as value"""
+
+        @param options(dict): dict with feature as key and choosed option as value
+        @param namespace (None, unicode): form namespace or None to ignore
+        """
         feature_elt = domish.Element((NS_FEATURE_NEG, 'feature'))
-        x_form = data_form.Form('submit')
-        x_form.makeFields(options_dict)
+        x_form = data_form.Form('submit', formNamespace=namespace)
+        x_form.makeFields(options)
         feature_elt.addChild(x_form.toElement())
         return feature_elt
 
-    def proposeFeatures(self, options_dict, namespace=None):
+    def proposeFeatures(self, options_dict, namespace):
         """Build a feature element with options to propose
-        @param options_dict: dict with feature as key and list of acceptable options as value
-        @param namespace: feature namespace"""
+
+        @param options_dict(dict): dict with feature as key and iterable of acceptable options as value
+        @param namespace(None, unicode): feature namespace
+        """
         feature_elt = domish.Element((NS_FEATURE_NEG, 'feature'))
         x_form = data_form.Form('form', formNamespace=namespace)
         for field in options_dict:
             x_form.addField(data_form.Field('list-single', field,
-                            options=[data_form.Option(_option) for _option in options_dict[field]]))
+                            options=[data_form.Option(option) for option in options_dict[field]]))
         feature_elt.addChild(x_form.toElement())
         return feature_elt