# HG changeset patch # User Goffi # Date 1451842402 -3600 # Node ID 34adc4a8aa6462bd468b5c2ebb50192ff92c9caf # Parent cca47e9977a503870cb24b1fb44387f02468ddc5 new container module, with an ItemData container: this simplify item data manipulation and transmission between storage and backend, it's also better if new data need to be used. diff -r cca47e9977a5 -r 34adc4a8aa64 sat_pubsub/backend.py --- a/sat_pubsub/backend.py Sun Jan 03 18:33:22 2016 +0100 +++ b/sat_pubsub/backend.py Sun Jan 03 18:33:22 2016 +0100 @@ -72,18 +72,18 @@ # from twisted.words.protocols.jabber.jid import JID, InvalidFormat from twisted.words.xish import utility -from wokkel import disco, data_form, rsm -from wokkel.iwokkel import IPubSubResource -from wokkel.pubsub import PubSubResource, PubSubError, Subscription +from wokkel import disco +from wokkel import data_form +from wokkel import rsm +from wokkel import iwokkel +from wokkel import pubsub -from sat_pubsub import error, iidavoll, const -from sat_pubsub.iidavoll import IBackendService, ILeafNode +from sat_pubsub import error +from sat_pubsub import iidavoll +from sat_pubsub import const +from sat_pubsub import container from copy import deepcopy -from collections import namedtuple - - -ItemData = namedtuple('ItemData', ('item', 'access_model', 'config', 'categories')) def _getAffiliation(node, entity): @@ -336,7 +336,7 @@ check_overwrite = True access_model, item_config = self.parseItemConfig(item) categories = self.parseCategories(item) - items_data.append(ItemData(item, access_model, item_config, categories)) + items_data.append(container.ItemData(item, access_model, item_config, categories)) if persistItems: if check_overwrite and affiliation != 'owner': @@ -594,11 +594,6 @@ log.msg("Error while getting roster of {}: {}".format(unicode(owner_jid), failure.value)) return {} - def _tuple2ItemData(self, items_data): - # FIXME: workaround for the use of ItemData which doesn't exist in storage - # must be done in a cleaner way - return [ItemData(item, access_model, access_list, []) for item, access_model, access_list in items_data] - def _doGetItems(self, result, requestor, maxItems, itemIdentifiers, ext_data): node, affiliation = result @@ -636,11 +631,9 @@ if itemIdentifiers: d = node.getItemsById(authorized_groups, unrestricted, itemIdentifiers) - d.addCallback(self._tuple2ItemData) else: d = node.getItems(authorized_groups, unrestricted, maxItems, ext_data) if unrestricted: - d.addCallback(self._tuple2ItemData) d.addCallback(append_item_config) try: @@ -654,7 +647,7 @@ rsm_data) return d - if not ILeafNode.providedBy(node): + if not iidavoll.ILeafNode.providedBy(node): return [] if affiliation == 'outcast': @@ -780,7 +773,6 @@ d = node.getItemsPublishers(itemIdentifiers) d.addCallback(checkPublishers) d.addCallback(lambda dummy: node.getItemsById(None, True, itemIdentifiers)) - d.addCallback(self._tuple2ItemData) d.addCallback(removeItems) if notify: @@ -876,7 +868,7 @@ -class PubSubResourceFromBackend(PubSubResource): +class PubSubResourceFromBackend(pubsub.PubSubResource): """ Adapts a backend to an xmpp publish-subscribe service. """ @@ -932,7 +924,7 @@ } def __init__(self, backend): - PubSubResource.__init__(self) + pubsub.PubSubResource.__init__(self) self.backend = backend self.hideNodes = False @@ -993,7 +985,7 @@ return new_item notifications_filtered.append((owner_jid, - set([Subscription(node.nodeIdentifier, + set([pubsub.Subscription(node.nodeIdentifier, owner_jid, 'subscribed')]), [getFullItem(item_data) for item_data in items_data])) @@ -1025,7 +1017,7 @@ #we add the owner notifications_filtered.append((owner_jid, - set([Subscription(node.nodeIdentifier, + set([pubsub.Subscription(node.nodeIdentifier, owner_jid, 'subscribed')]), [item_data.item for item_data in items_data])) @@ -1143,7 +1135,7 @@ msg = failure.value.msg if pubsubCondition: - exc = PubSubError(condition, pubsubCondition, feature, msg) + exc = pubsub.PubSubError(condition, pubsubCondition, feature, msg) else: exc = StanzaError(condition, text=msg) @@ -1326,5 +1318,5 @@ return d.addErrback(self._mapErrors) components.registerAdapter(PubSubResourceFromBackend, - IBackendService, - IPubSubResource) + iidavoll.IBackendService, + iwokkel.IPubSubResource) diff -r cca47e9977a5 -r 34adc4a8aa64 sat_pubsub/container.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sat_pubsub/container.py Sun Jan 03 18:33:22 2016 +0100 @@ -0,0 +1,24 @@ +#!/usr/bin/python +#-*- coding: utf-8 -*- + +# Copyright (C) 2016 Jérôme Poisson (goffi@goffi.org) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + + +from collections import namedtuple + + +ItemData = namedtuple('ItemData', ('item', 'access_model', 'config', 'categories')) +ItemData.__new__.__defaults__ = (None,) * (len(ItemData._fields) - 1) # Only item is mandatory diff -r cca47e9977a5 -r 34adc4a8aa64 sat_pubsub/pgsql_storage.py --- a/sat_pubsub/pgsql_storage.py Sun Jan 03 18:33:22 2016 +0100 +++ b/sat_pubsub/pgsql_storage.py Sun Jan 03 18:33:22 2016 +0100 @@ -61,7 +61,10 @@ from wokkel import generic from wokkel.pubsub import Subscription -from sat_pubsub import error, iidavoll, const +from sat_pubsub import error +from sat_pubsub import iidavoll +from sat_pubsub import const +from sat_pubsub import container import psycopg2 import psycopg2.extensions # we wants psycopg2 to return us unicode, not str @@ -689,7 +692,8 @@ @param rsm_data: options for RSM feature handling (XEP-0059) as a dictionnary of C{unicode} to C{unicode}. - @return: list of (item, access_model, id) if unrestricted is True, else list of items + @return: list of container.ItemData + if unrestricted is False, access_model and config will be None """ if ext_data is None: ext_data = {} @@ -778,10 +782,10 @@ cursor.execute('SELECT groupname FROM item_groups_authorized WHERE item_id=%s', (item_id,)) access_list[const.OPT_ROSTER_GROUPS_ALLOWED] = [r[0] for r in cursor.fetchall()] - ret.append((item, access_model, access_list)) + ret.append(container.ItemData(item, access_model, access_list)) return ret - items = [generic.stripNamespace(parseXml(r[0])) for r in result] - return items + items_data = [container.ItemData(generic.stripNamespace(parseXml(r[0])), None, None) for r in result] + return items_data def countItems(self, authorized_groups, unrestricted): """ Count the accessible items. @@ -793,6 +797,7 @@ return self.dbpool.runInteraction(self._countItems, authorized_groups, unrestricted) def _countItems(self, cursor, authorized_groups, unrestricted): + # FIXME: should not be a separate method, but should be an option of getItems instead self._checkNodeExists(cursor) if unrestricted: @@ -862,8 +867,9 @@ @param authorized_groups: we want to get items that these groups can access @param unrestricted: if true, don't check permissions @param itemIdentifiers: list of ids of the items we want to get - @return: list of (item, access_model, access_list) if unrestricted is True, else list of items - access_list is managed as a dictionnary with same key as for item_config + @return: list of container.ItemData + ItemData.config will contains access_list (managed as a dictionnary with same key as for item_config) + if unrestricted is False, access_model and config will be None """ return self.dbpool.runInteraction(self._getItemsById, authorized_groups, unrestricted, itemIdentifiers) @@ -890,7 +896,7 @@ cursor.execute('SELECT groupname FROM item_groups_authorized WHERE item_id=%s', (item_id,)) access_list[const.OPT_ROSTER_GROUPS_ALLOWED] = [r[0] for r in cursor.fetchall()] - ret.append((item, access_model, access_list)) + ret.append(container.ItemData(item, access_model, access_list)) else: #we check permission before returning items for itemIdentifier in itemIdentifiers: args = [self.nodeDbId, itemIdentifier] @@ -906,7 +912,7 @@ result = cursor.fetchone() if result: - ret.append(generic.stripNamespace(parseXml(result[0]))) + ret.append(container.ItemData(generic.stripNamespace(parseXml(result[0])), None, None)) return ret