Mercurial > libervia-backend
diff sat/plugins/plugin_xep_0055.py @ 2624:56f94936df1e
code style reformatting using black
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 27 Jun 2018 20:14:46 +0200 |
parents | 26edcf3a30eb |
children | 378188abe941 |
line wrap: on
line diff
--- a/sat/plugins/plugin_xep_0055.py Wed Jun 27 07:51:29 2018 +0200 +++ b/sat/plugins/plugin_xep_0055.py Wed Jun 27 20:14:46 2018 +0200 @@ -19,6 +19,7 @@ from sat.core.i18n import _, D_ from sat.core.log import getLogger + log = getLogger(__name__) from twisted.words.protocols.jabber.xmlstream import IQ @@ -30,6 +31,7 @@ from sat.tools import xml_tools from wokkel import disco, iwokkel + try: from twisted.words.protocols.xmlstream import XMPPHandler except ImportError: @@ -37,7 +39,7 @@ from zope.interface import implements -NS_SEARCH = 'jabber:iq:search' +NS_SEARCH = "jabber:iq:search" PLUGIN_INFO = { C.PI_NAME: "Jabber Search", @@ -48,7 +50,7 @@ C.PI_RECOMMENDATIONS: ["XEP-0059"], C.PI_MAIN: "XEP_0055", C.PI_HANDLER: "no", - C.PI_DESCRIPTION: _("""Implementation of Jabber Search""") + C.PI_DESCRIPTION: _("""Implementation of Jabber Search"""), } # config file parameters @@ -58,26 +60,48 @@ DEFAULT_SERVICE_LIST = ["salut.libervia.org"] FIELD_SINGLE = "field_single" # single text field for the simple search -FIELD_CURRENT_SERVICE = "current_service_jid" # read-only text field for the advanced search +FIELD_CURRENT_SERVICE = ( + "current_service_jid" +) # read-only text field for the advanced search + class XEP_0055(object): - def __init__(self, host): log.info(_("Jabber search plugin initialization")) self.host = host # default search services (config file + hard-coded lists) - self.services = [jid.JID(entry) for entry in host.memory.getConfig(CONFIG_SECTION, CONFIG_SERVICE_LIST, DEFAULT_SERVICE_LIST)] + self.services = [ + jid.JID(entry) + for entry in host.memory.getConfig( + CONFIG_SECTION, CONFIG_SERVICE_LIST, DEFAULT_SERVICE_LIST + ) + ] - host.bridge.addMethod("searchGetFieldsUI", ".plugin", in_sign='ss', out_sign='s', - method=self._getFieldsUI, - async=True) - host.bridge.addMethod("searchRequest", ".plugin", in_sign='sa{ss}s', out_sign='s', - method=self._searchRequest, - async=True) + host.bridge.addMethod( + "searchGetFieldsUI", + ".plugin", + in_sign="ss", + out_sign="s", + method=self._getFieldsUI, + async=True, + ) + host.bridge.addMethod( + "searchRequest", + ".plugin", + in_sign="sa{ss}s", + out_sign="s", + method=self._searchRequest, + async=True, + ) self.__search_menu_id = host.registerCallback(self._getMainUI, with_data=True) - host.importMenu((D_("Contacts"), D_("Search directory")), self._getMainUI, security_limit=1, help_string=D_("Search user directory")) + host.importMenu( + (D_("Contacts"), D_("Search directory")), + self._getMainUI, + security_limit=1, + help_string=D_("Search user directory"), + ) def _getHostServices(self, profile): """Return the jabber search services associated to the user host. @@ -89,10 +113,8 @@ d = self.host.findFeaturesSet(client, [NS_SEARCH]) return d.addCallback(lambda set_: list(set_)) - ## Main search UI (menu item callback) ## - def _getMainUI(self, raw_data, profile): """Get the XMLUI for selecting a service and searching the directory. @@ -115,11 +137,18 @@ # extend services offered by user's server with the default services services.extend([service for service in self.services if service not in services]) data = xml_tools.XMLUIResult2DataFormResult(raw_data) - main_ui = xml_tools.XMLUI(C.XMLUI_WINDOW, container="tabs", title=_("Search users"), submit_id=self.__search_menu_id) + main_ui = xml_tools.XMLUI( + C.XMLUI_WINDOW, + container="tabs", + title=_("Search users"), + submit_id=self.__search_menu_id, + ) d = self._addSimpleSearchUI(services, main_ui, data, profile) - d.addCallback(lambda dummy: self._addAdvancedSearchUI(services, main_ui, data, profile)) - return d.addCallback(lambda dummy: {'xmlui': main_ui.toXml()}) + d.addCallback( + lambda dummy: self._addAdvancedSearchUI(services, main_ui, data, profile) + ) + return d.addCallback(lambda dummy: {"xmlui": main_ui.toXml()}) def _addSimpleSearchUI(self, services, main_ui, data, profile): """Add to the main UI a tab for the simple search. @@ -133,32 +162,49 @@ @return: a dummy Deferred """ - service_jid = services[0] # TODO: search on all the given services, not only the first one + service_jid = services[ + 0 + ] # TODO: search on all the given services, not only the first one - form = data_form.Form('form', formNamespace=NS_SEARCH) - form.addField(data_form.Field('text-single', FIELD_SINGLE, label=_('Search for'), value=data.get(FIELD_SINGLE, ''))) + form = data_form.Form("form", formNamespace=NS_SEARCH) + form.addField( + data_form.Field( + "text-single", + FIELD_SINGLE, + label=_("Search for"), + value=data.get(FIELD_SINGLE, ""), + ) + ) - sub_cont = main_ui.main_container.addTab("simple_search", label=_("Simple search"), container=xml_tools.VerticalContainer) + sub_cont = main_ui.main_container.addTab( + "simple_search", + label=_("Simple search"), + container=xml_tools.VerticalContainer, + ) main_ui.changeContainer(sub_cont.append(xml_tools.PairsContainer(main_ui))) xml_tools.dataForm2Widgets(main_ui, form) # FIXME: add colspan attribute to divider? (we are in a PairsContainer) - main_ui.addDivider('blank') - main_ui.addDivider('blank') # here we added a blank line before the button - main_ui.addDivider('blank') + main_ui.addDivider("blank") + main_ui.addDivider("blank") # here we added a blank line before the button + main_ui.addDivider("blank") main_ui.addButton(self.__search_menu_id, _("Search"), (FIELD_SINGLE,)) - main_ui.addDivider('blank') - main_ui.addDivider('blank') # a blank line again after the button + main_ui.addDivider("blank") + main_ui.addDivider("blank") # a blank line again after the button - simple_data = {key: value for key, value in data.iteritems() if key in (FIELD_SINGLE,)} + simple_data = { + key: value for key, value in data.iteritems() if key in (FIELD_SINGLE,) + } if simple_data: log.debug("Simple search with %s on %s" % (simple_data, service_jid)) sub_cont.parent.setSelected(True) main_ui.changeContainer(sub_cont.append(xml_tools.VerticalContainer(main_ui))) - main_ui.addDivider('dash') + main_ui.addDivider("dash") d = self.searchRequest(service_jid, simple_data, profile) - d.addCallbacks(lambda elt: self._displaySearchResult(main_ui, elt), - lambda failure: main_ui.addText(failure.getErrorMessage())) + d.addCallbacks( + lambda elt: self._displaySearchResult(main_ui, elt), + lambda failure: main_ui.addText(failure.getErrorMessage()), + ) return d return defer.succeed(None) @@ -175,16 +221,20 @@ @return: a dummy Deferred """ - sub_cont = main_ui.main_container.addTab("advanced_search", label=_("Advanced search"), container=xml_tools.VerticalContainer) - service_selection_fields = ['service_jid', 'service_jid_extra'] + sub_cont = main_ui.main_container.addTab( + "advanced_search", + label=_("Advanced search"), + container=xml_tools.VerticalContainer, + ) + service_selection_fields = ["service_jid", "service_jid_extra"] - if 'service_jid_extra' in data: + if "service_jid_extra" in data: # refresh button has been pushed, select the tab sub_cont.parent.setSelected(True) # get the selected service - service_jid_s = data.get('service_jid_extra', '') + service_jid_s = data.get("service_jid_extra", "") if not service_jid_s: - service_jid_s = data.get('service_jid', unicode(services[0])) + service_jid_s = data.get("service_jid", unicode(services[0])) log.debug("Refreshing search fields for %s" % service_jid_s) else: service_jid_s = data.get(FIELD_CURRENT_SERVICE, unicode(services[0])) @@ -194,27 +244,32 @@ main_ui.changeContainer(sub_cont.append(xml_tools.PairsContainer(main_ui))) main_ui.addLabel(_("Search on")) - main_ui.addList('service_jid', options=services_s, selected=service_jid_s) + main_ui.addList("service_jid", options=services_s, selected=service_jid_s) main_ui.addLabel(_("Other service")) - main_ui.addString(name='service_jid_extra') + main_ui.addString(name="service_jid_extra") # FIXME: add colspan attribute to divider? (we are in a PairsContainer) - main_ui.addDivider('blank') - main_ui.addDivider('blank') # here we added a blank line before the button - main_ui.addDivider('blank') - main_ui.addButton(self.__search_menu_id, _("Refresh fields"), service_selection_fields) - main_ui.addDivider('blank') - main_ui.addDivider('blank') # a blank line again after the button + main_ui.addDivider("blank") + main_ui.addDivider("blank") # here we added a blank line before the button + main_ui.addDivider("blank") + main_ui.addButton( + self.__search_menu_id, _("Refresh fields"), service_selection_fields + ) + main_ui.addDivider("blank") + main_ui.addDivider("blank") # a blank line again after the button main_ui.addLabel(_("Displaying the search form for")) main_ui.addString(name=FIELD_CURRENT_SERVICE, value=service_jid_s, read_only=True) - main_ui.addDivider('dash') - main_ui.addDivider('dash') + main_ui.addDivider("dash") + main_ui.addDivider("dash") main_ui.changeContainer(sub_cont.append(xml_tools.VerticalContainer(main_ui))) service_jid = jid.JID(service_jid_s) d = self.getFieldsUI(service_jid, profile) - d.addCallbacks(self._addAdvancedForm, lambda failure: main_ui.addText(failure.getErrorMessage()), - [service_jid, main_ui, sub_cont, data, profile]) + d.addCallbacks( + self._addAdvancedForm, + lambda failure: main_ui.addText(failure.getErrorMessage()), + [service_jid, main_ui, sub_cont, data, profile], + ) return d def _addAdvancedForm(self, form_elt, service_jid, main_ui, sub_cont, data, profile): @@ -243,26 +298,29 @@ widget.setAttribute("value", adv_data[name]) # FIXME: add colspan attribute to divider? (we are in a PairsContainer) - main_ui.addDivider('blank') - main_ui.addDivider('blank') # here we added a blank line before the button - main_ui.addDivider('blank') - main_ui.addButton(self.__search_menu_id, _("Search"), adv_fields + [FIELD_CURRENT_SERVICE]) - main_ui.addDivider('blank') - main_ui.addDivider('blank') # a blank line again after the button + main_ui.addDivider("blank") + main_ui.addDivider("blank") # here we added a blank line before the button + main_ui.addDivider("blank") + main_ui.addButton( + self.__search_menu_id, _("Search"), adv_fields + [FIELD_CURRENT_SERVICE] + ) + main_ui.addDivider("blank") + main_ui.addDivider("blank") # a blank line again after the button if adv_data: # display the search results log.debug("Advanced search with %s on %s" % (adv_data, service_jid)) sub_cont.parent.setSelected(True) main_ui.changeContainer(sub_cont.append(xml_tools.VerticalContainer(main_ui))) - main_ui.addDivider('dash') + main_ui.addDivider("dash") d = self.searchRequest(service_jid, adv_data, profile) - d.addCallbacks(lambda elt: self._displaySearchResult(main_ui, elt), - lambda failure: main_ui.addText(failure.getErrorMessage())) + d.addCallbacks( + lambda elt: self._displaySearchResult(main_ui, elt), + lambda failure: main_ui.addText(failure.getErrorMessage()), + ) return d return defer.succeed(None) - def _displaySearchResult(self, main_ui, elt): """Display the search results. @@ -277,7 +335,9 @@ header = headers.keys()[i % len(headers)] widget_type, widget_args, widget_kwargs = xmlui_data[i] value = widget_args[0] - values.setdefault(header, []).append(jid.JID(value) if header == "jid" else value) + values.setdefault(header, []).append( + jid.JID(value) if header == "jid" else value + ) main_ui.addJidsList(jids=values["jid"], name=D_(u"Search results")) # TODO: also display the values other than JID else: @@ -285,10 +345,8 @@ else: main_ui.addText(D_("The search gave no result")) - ## Retrieve the search fields ## - def _getFieldsUI(self, to_jid_s, profile_key): """Ask a service to send us the list of the form fields it manages. @@ -308,10 +366,10 @@ @return: a deferred domish.Element """ client = self.host.getClient(profile_key) - fields_request = IQ(client.xmlstream, 'get') + fields_request = IQ(client.xmlstream, "get") fields_request["from"] = client.jid.full() fields_request["to"] = to_jid.full() - fields_request.addElement('query', NS_SEARCH) + fields_request.addElement("query", NS_SEARCH) d = fields_request.send(to_jid.full()) d.addCallbacks(self._getFieldsUICb, self._getFieldsUIEb) return d @@ -323,15 +381,17 @@ @return: domish.Element """ try: - query_elts = answer.elements('jabber:iq:search', 'query').next() + query_elts = answer.elements("jabber:iq:search", "query").next() except StopIteration: log.info(_("No query element found")) raise DataError # FIXME: StanzaError is probably more appropriate, check the RFC try: - form_elt = query_elts.elements(data_form.NS_X_DATA, 'x').next() + form_elt = query_elts.elements(data_form.NS_X_DATA, "x").next() except StopIteration: log.info(_("No data form found")) - raise NotImplementedError("Only search through data form is implemented so far") + raise NotImplementedError( + "Only search through data form is implemented so far" + ) return form_elt def _getFieldsUIEb(self, failure): @@ -343,10 +403,8 @@ log.info(_("Fields request failure: %s") % unicode(failure.getErrorMessage())) raise failure - ## Do the search ## - def _searchRequest(self, to_jid_s, search_data, profile_key): """Actually do a search, according to filled data. @@ -370,15 +428,17 @@ if FIELD_SINGLE in search_data: value = search_data[FIELD_SINGLE] d = self.getFieldsUI(to_jid, profile_key) - d.addCallback(lambda elt: self.searchRequestMulti(to_jid, value, elt, profile_key)) + d.addCallback( + lambda elt: self.searchRequestMulti(to_jid, value, elt, profile_key) + ) return d client = self.host.getClient(profile_key) - search_request = IQ(client.xmlstream, 'set') + search_request = IQ(client.xmlstream, "set") search_request["from"] = client.jid.full() search_request["to"] = to_jid.full() - query_elt = search_request.addElement('query', NS_SEARCH) - x_form = data_form.Form('submit', formNamespace=NS_SEARCH) + query_elt = search_request.addElement("query", NS_SEARCH) + x_form = data_form.Form("submit", formNamespace=NS_SEARCH) x_form.makeFields(search_data) query_elt.addChild(x_form.toElement()) # TODO: XEP-0059 could be used here (with the needed new method attributes) @@ -406,13 +466,17 @@ for success, form_elt in result: if not success: continue - if result_elt is None: # the result element is built over the first answer + if ( + result_elt is None + ): # the result element is built over the first answer result_elt = form_elt continue - for item_elt in form_elt.elements('jabber:x:data', 'item'): + for item_elt in form_elt.elements("jabber:x:data", "item"): result_elt.addChild(item_elt) if result_elt is None: - raise defer.failure.Failure(DataError(_("The search could not be performed"))) + raise defer.failure.Failure( + DataError(_("The search could not be performed")) + ) return result_elt return defer.DeferredList(d_list).addCallback(cb) @@ -424,15 +488,17 @@ @return: domish.Element """ try: - query_elts = answer.elements('jabber:iq:search', 'query').next() + query_elts = answer.elements("jabber:iq:search", "query").next() except StopIteration: log.info(_("No query element found")) raise DataError # FIXME: StanzaError is probably more appropriate, check the RFC try: - form_elt = query_elts.elements(data_form.NS_X_DATA, 'x').next() + form_elt = query_elts.elements(data_form.NS_X_DATA, "x").next() except StopIteration: log.info(_("No data form found")) - raise NotImplementedError("Only search through data form is implemented so far") + raise NotImplementedError( + "Only search through data form is implemented so far" + ) return form_elt def _searchErr(self, failure): @@ -453,9 +519,8 @@ self.host = plugin_parent.host self.profile = profile - def getDiscoInfo(self, requestor, target, nodeIdentifier=''): + def getDiscoInfo(self, requestor, target, nodeIdentifier=""): return [disco.DiscoFeature(NS_SEARCH)] - def getDiscoItems(self, requestor, target, nodeIdentifier=''): + def getDiscoItems(self, requestor, target, nodeIdentifier=""): return [] -