# HG changeset patch # User Goffi # Date 1458683164 -3600 # Node ID d3354c80bd1ffd5b1379af0daf08d33af90cff91 # Parent 01d56efd488bc037e9e4f1bfd89f2a8637649a50 core (tools): moved common to a separate package, and put data method in a data_format module diff -r 01d56efd488b -r d3354c80bd1f frontends/src/jp/cmd_blog.py --- a/frontends/src/jp/cmd_blog.py Mon Mar 21 19:44:16 2016 +0100 +++ b/frontends/src/jp/cmd_blog.py Tue Mar 22 22:46:04 2016 +0100 @@ -32,7 +32,7 @@ import subprocess import shlex import glob -from sat.tools import common +from sat.tools.common import data_format __commands__ = ["Blog"] @@ -187,7 +187,7 @@ # and override metadata with command-line arguments mb_data['allow_comments'] = C.boolConst(not self.args.no_comment) if self.args.tag: - common.iter2dict('tag', self.args.tag, mb_data) + data_format.iter2dict('tag', self.args.tag, mb_data) if self.args.title is not None: mb_data['title'] = self.args.title diff -r 01d56efd488b -r d3354c80bd1f frontends/src/quick_frontend/quick_blog.py --- a/frontends/src/quick_frontend/quick_blog.py Mon Mar 21 19:44:16 2016 +0100 +++ b/frontends/src/quick_frontend/quick_blog.py Tue Mar 22 22:46:04 2016 +0100 @@ -25,7 +25,7 @@ from sat_frontends.quick_frontend.constants import Const as C from sat_frontends.quick_frontend import quick_widgets from sat_frontends.tools import jid -from sat.tools import common +from sat.tools.common import data_format try: # FIXME: to be removed when an acceptable solution is here @@ -49,7 +49,7 @@ self.title = data.get('title') self.title_rich = None self.title_xhtml = data.get('title_xhtml') - self.tags = list(common.dict2iter('tag', data)) + self.tags = list(data_format.dict2iter('tag', data)) self.content = data.get('content') self.content_rich = None self.content_xhtml = data.get('content_xhtml') @@ -264,7 +264,7 @@ if value is not None: mb_data[name] = value - common.iter2dict('tag', self.item.tags, mb_data) + data_format.iter2dict('tag', self.item.tags, mb_data) if self.blog.new_message_target not in (C.PUBLIC, C.GROUP): raise NotImplementedError @@ -273,7 +273,7 @@ mb_data["allow_comments"] = C.BOOL_TRUE if self.blog.new_message_target == C.GROUP: - common.iter2dict('group', self.blog.targets, mb_data) + data_format.iter2dict('group', self.blog.targets, mb_data) self.blog.host.bridge.mbSend( unicode(self.service or ''), diff -r 01d56efd488b -r d3354c80bd1f src/plugins/plugin_blog_import_dotclear.py --- a/src/plugins/plugin_blog_import_dotclear.py Mon Mar 21 19:44:16 2016 +0100 +++ b/src/plugins/plugin_blog_import_dotclear.py Tue Mar 22 22:46:04 2016 +0100 @@ -22,7 +22,7 @@ from sat.core.log import getLogger log = getLogger(__name__) from sat.core import exceptions -from sat.tools import common +from sat.tools.common import data_format from twisted.internet import threads from collections import OrderedDict import itertools @@ -159,7 +159,7 @@ def metaFinishedHandler(self): for post_id, tags in self.tags.iteritems(): - common.iter2dict('tag', tags, self.posts_data[post_id]['blog']) + data_format.iter2dict('tag', tags, self.posts_data[post_id]['blog']) del self.tags def commentHandler(self, headers, data, index): diff -r 01d56efd488b -r d3354c80bd1f src/plugins/plugin_misc_groupblog.py --- a/src/plugins/plugin_misc_groupblog.py Mon Mar 21 19:44:16 2016 +0100 +++ b/src/plugins/plugin_misc_groupblog.py Tue Mar 22 22:46:04 2016 +0100 @@ -25,7 +25,7 @@ from sat.core import exceptions from wokkel import disco, data_form, iwokkel from zope.interface import implements -from sat.tools import common +from sat.tools.common import data_format try: from twisted.words.protocols.xmlstream import XMPPHandler @@ -102,7 +102,7 @@ access_model = config_form.get(self._p.OPT_ACCESS_MODEL, self._p.ACCESS_OPEN) # FIXME: ACCESS_ROSTER need to be changed to a new ACCESS_PUBLISHER_ROSTER when available if access_model == self._p.ACCESS_ROSTER: - common.iter2dict('group', config_form.fields[self._p.OPT_ROSTER_GROUPS_ALLOWED].values, microblog_data) + data_format.iter2dict('group', config_form.fields[self._p.OPT_ROSTER_GROUPS_ALLOWED].values, microblog_data) def _data2entryTrigger(self, client, mb_data, entry_elt, item_elt): """Build fine access permission if needed @@ -110,7 +110,7 @@ This trigger check if "group*" key are present, and create a fine item config to restrict view to these groups """ - groups = list(common.dict2iter('group', mb_data)) + groups = list(data_format.dict2iter('group', mb_data)) if not groups: return if not client.server_groupblog_available: @@ -132,7 +132,7 @@ if "group" in mb_data: # FIXME: ACCESS_ROSTER need to be changed to a new ACCESS_PUBLISHER_ROSTER when available options[self._p.OPT_ACCESS_MODEL] = self._p.ACCESS_ROSTER - options[self._p.OPT_ROSTER_GROUPS_ALLOWED] = list(common.dict2iter('group', mb_data)) + options[self._p.OPT_ROSTER_GROUPS_ALLOWED] = list(data_format.dict2iter('group', mb_data)) class GroupBlog_handler(XMPPHandler): diff -r 01d56efd488b -r d3354c80bd1f src/plugins/plugin_xep_0277.py --- a/src/plugins/plugin_xep_0277.py Mon Mar 21 19:44:16 2016 +0100 +++ b/src/plugins/plugin_xep_0277.py Tue Mar 22 22:46:04 2016 +0100 @@ -28,7 +28,7 @@ from sat.core import exceptions from sat.tools import xml_tools from sat.tools import sat_defer -from sat.tools import common +from sat.tools.common import data_format # XXX: tmp.pubsub is actually use instead of wokkel version from wokkel import pubsub @@ -326,7 +326,7 @@ # categories categories = (category_elt.getAttribute('term','') for category_elt in entry_elt.elements(NS_ATOM, 'category')) - common.iter2dict('tag', categories, microblog_data) + data_format.iter2dict('tag', categories, microblog_data) ## the trigger ## # if other plugins have things to add or change @@ -426,7 +426,7 @@ content=rfc3339.timestamp_from_tf(float(data.get('published', current_time)))) ## categories ## - for tag in common.dict2iter("tag", data): + for tag in data_format.dict2iter("tag", data): category_elt = entry_elt.addElement("category") category_elt['term'] = tag diff -r 01d56efd488b -r d3354c80bd1f src/tools/common.py --- a/src/tools/common.py Mon Mar 21 19:44:16 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# SAT: a jabber client -# Copyright (C) 2009-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 . - -""" tools common to backend and frontends """ - -from sat.core import exceptions - - -def dict2iter(name, dict_, pop=False): - """iterate into a list serialised in a dict - - name is the name of the key. - Serialisation is done with [name] [name#1] [name#2] and so on - e.g.: if name is 'group', keys are group, group#1, group#2, ... - iteration stop at first missing increment - Empty values are possible - @param name(unicode): name of the key - @param mb_data (dict): dictionary with the serialised list - @param pop(bool): if True, remove the value from dict - @return iter: iterate through the deserialised list - """ - if pop: - get=lambda d,k: d.pop(k) - else: - get=lambda d,k: d[k] - - try: - yield get(dict_,name) - except KeyError: - return - else: - idx = 1 - while True: - try: - yield get(dict_,u'{}#{}'.format(name, idx)) - except KeyError: - return - else: - idx += 1 - -def iter2dict(name, iter_, dict_=None, check_conflict=True): - """Fill a dict with values from an iterable - - name is used to serialise iter_, in the same way as in [dict2iter] - Build from the tags a dict using the microblog data format. - - @param name(unicode): key to use for serialisation - e.g. "group" to have keys "group", "group#1", "group#2", ... - @param iter_(iterable): values to store - @param dict_(None, dict): dictionary to fill, or None to create one - @param check_conflict(bool): if True, raise an exception in case of existing key - @return (dict): filled dict, or newly created one - @raise exceptions.ConflictError: a needed key already exists - """ - if dict_ is None: - dict_ = {} - for idx, value in enumerate(iter_): - if idx == 0: - key = name - else: - key = u'{}#{}'.format(name, idx) - if check_conflict and key in dict_: - raise exceptions.ConflictError - dict_[key] = value - return dict diff -r 01d56efd488b -r d3354c80bd1f src/tools/common/data_format.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tools/common/data_format.py Tue Mar 22 22:46:04 2016 +0100 @@ -0,0 +1,81 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# SAT: a jabber client +# Copyright (C) 2009-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 . + +""" tools common to backend and frontends """ + +from sat.core import exceptions + + +def dict2iter(name, dict_, pop=False): + """iterate into a list serialised in a dict + + name is the name of the key. + Serialisation is done with [name] [name#1] [name#2] and so on + e.g.: if name is 'group', keys are group, group#1, group#2, ... + iteration stop at first missing increment + Empty values are possible + @param name(unicode): name of the key + @param mb_data (dict): dictionary with the serialised list + @param pop(bool): if True, remove the value from dict + @return iter: iterate through the deserialised list + """ + if pop: + get=lambda d,k: d.pop(k) + else: + get=lambda d,k: d[k] + + try: + yield get(dict_,name) + except KeyError: + return + else: + idx = 1 + while True: + try: + yield get(dict_,u'{}#{}'.format(name, idx)) + except KeyError: + return + else: + idx += 1 + +def iter2dict(name, iter_, dict_=None, check_conflict=True): + """Fill a dict with values from an iterable + + name is used to serialise iter_, in the same way as in [dict2iter] + Build from the tags a dict using the microblog data format. + + @param name(unicode): key to use for serialisation + e.g. "group" to have keys "group", "group#1", "group#2", ... + @param iter_(iterable): values to store + @param dict_(None, dict): dictionary to fill, or None to create one + @param check_conflict(bool): if True, raise an exception in case of existing key + @return (dict): filled dict, or newly created one + @raise exceptions.ConflictError: a needed key already exists + """ + if dict_ is None: + dict_ = {} + for idx, value in enumerate(iter_): + if idx == 0: + key = name + else: + key = u'{}#{}'.format(name, idx) + if check_conflict and key in dict_: + raise exceptions.ConflictError + dict_[key] = value + return dict