plugins schema, tickets, merge_requests: use serialised data for extra dict + some cosmetic changes

This commit is contained in:
Goffi 2019-06-14 12:37:34 +02:00
commit 481ce4c379
5 changed files with 94 additions and 72 deletions

View file

@ -17,37 +17,38 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from collections import Iterable
import copy
import itertools
from zope.interface import implements
from twisted.words.protocols.jabber import jid
from twisted.words.protocols.jabber.xmlstream import XMPPHandler
from twisted.internet import defer
from wokkel import disco, iwokkel
from wokkel import data_form
from wokkel import generic
from sat.core.i18n import _
from sat.core import exceptions
from sat.core.constants import Const as C
from sat.tools import xml_tools
from sat.tools import utils
from sat.tools.common import date_utils
from twisted.words.protocols.jabber import jid
from twisted.words.protocols.jabber.xmlstream import XMPPHandler
from twisted.internet import defer
from sat.tools.common import data_format
from sat.core.log import getLogger
log = getLogger(__name__)
from wokkel import disco, iwokkel
from wokkel import data_form
from wokkel import generic
from zope.interface import implements
from collections import Iterable
import copy
import itertools
NS_SCHEMA = "https://salut-a-toi/protocol/schema:0"
NS_SCHEMA = u"https://salut-a-toi/protocol/schema:0"
PLUGIN_INFO = {
C.PI_NAME: "PubSub Schema",
C.PI_IMPORT_NAME: "PUBSUB_SCHEMA",
C.PI_TYPE: "EXP",
C.PI_NAME: u"PubSub Schema",
C.PI_IMPORT_NAME: u"PUBSUB_SCHEMA",
C.PI_TYPE: u"EXP",
C.PI_PROTOCOLS: [],
C.PI_DEPENDENCIES: ["XEP-0060", "IDENTITY"],
C.PI_MAIN: "PubsubSchema",
C.PI_HANDLER: "yes",
C.PI_DESCRIPTION: _("""Handle Pubsub data schemas"""),
C.PI_DEPENDENCIES: [u"XEP-0060", u"IDENTITY"],
C.PI_MAIN: u"PubsubSchema",
C.PI_HANDLER: u"yes",
C.PI_DESCRIPTION: _(u"""Handle Pubsub data schemas"""),
}
@ -510,10 +511,49 @@ class PubsubSchema(object):
schema = generic.parseXml(schema.encode("utf-8"))
else:
schema = None
if extra and u"update" in extra:
extra[u"update"] = C.bool(extra[u"update"])
extra = data_format.deserialise(extra)
return client, service, node or None, schema, item_id or None, extra
@defer.inlineCallbacks
def copyMissingValues(self, client, service, node, item_id, form_ns, values):
"""Retrieve values existing in original item and missing in update
Existing item will be retrieve, and values not already specified in values will
be filled
@param service: same as for [XEP_0060.getItems]
@param node: same as for [XEP_0060.getItems]
@param item_id(unicode): id of the item to retrieve
@param form_ns (unicode, None): namespace of the form
@param values(dict): values to fill
This dict will be modified *in place* to fill value present in existing
item and missing in the dict.
"""
try:
# we get previous item
items_data = yield self._p.getItems(
client, service, node, item_ids=[item_id]
)
item_elt = items_data[0][0]
except Exception as e:
log.warning(
_(u"Can't get previous item, update ignored: {reason}").format(
reason=e
)
)
else:
# and parse it
form = data_form.findForm(item_elt, form_ns)
if form is None:
log.warning(
_(
u"Can't parse previous item, update ignored: data form not found"
).format(reason=e)
)
else:
for name, field in form.fields.iteritems():
if name not in values:
values[name] = u"\n".join(unicode(v) for v in field.values)
def _set(self, service, node, values, schema=None, item_id=None, extra=None,
default_node=None, form_ns=None, fill_author=True,
profile_key=C.PROF_KEY_NONE):
@ -561,6 +601,8 @@ class PubsubSchema(object):
other arguments are same as for [self._s.sendDataFormItem]
@return (unicode): id of the created item
"""
if extra is None:
extra = {}
if not node:
if default_node is None:
raise ValueError(_(u"default_node must be set if node is not set"))
@ -573,31 +615,7 @@ class PubsubSchema(object):
raise exceptions.DataError(
_(u'if extra["update"] is set, item_id must be set too')
)
try:
# we get previous item
items_data = yield self._p.getItems(
client, service, node, item_ids=[item_id]
)
item_elt = items_data[0][0]
except Exception as e:
log.warning(
_(u"Can't get previous item, update ignored: {reason}").format(
reason=e
)
)
else:
# and parse it
form = data_form.findForm(item_elt, form_ns)
if form is None:
log.warning(
_(
u"Can't parse previous item, update ignored: data form not found"
).format(reason=e)
)
else:
for name, field in form.fields.iteritems():
if name not in values:
values[name] = u"\n".join(unicode(v) for v in field.values)
yield self.copyMissingValues(client, service, node, item_id, form_ns, values)
values["updated"] = now
if fill_author:

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# SAT plugin for Pubsub Schemas
# SAT plugin for pubsub forums
# Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org)
# This program is free software: you can redistribute it and/or modify
@ -83,7 +83,7 @@ class forums(object):
@defer.inlineCallbacks
def _createForums(self, client, forums, service, node, forums_elt=None, names=None):
"""recursively create <forums> element(s)
"""Recursively create <forums> element(s)
@param forums(list): forums which may have subforums
@param service(jid.JID): service where the new nodes will be created
@ -139,7 +139,7 @@ class forums(object):
defer.returnValue(forums_elt)
def _parseForums(self, parent_elt=None, forums=None):
"""recursivly parse a <forums> elements and return corresponding forums data
"""Recursivly parse a <forums> elements and return corresponding forums data
@param item(domish.Element): item with <forums> element
@param parent_elt(domish.Element, None): element to parse
@ -220,7 +220,7 @@ class forums(object):
@defer.inlineCallbacks
def set(self, client, forums, service=None, node=None, forums_key=None):
"""create or replace forums structure
"""Create or replace forums structure
@param forums(list): list of dictionary as follow:
a dictionary represent a forum metadata, with the following keys:
@ -254,7 +254,7 @@ class forums(object):
@defer.inlineCallbacks
def getTopics(self, client, service, node, rsm_request=None, extra=None):
"""retrieve topics data
"""Retrieve topics data
Topics are simple microblog URIs with some metadata duplicated from first post
"""

View file

@ -79,7 +79,7 @@ class MergeRequests(object):
async=True
)
host.bridge.addMethod("mergeRequestSet", ".plugin",
in_sign='ssssa{sas}ssa{ss}s', out_sign='s',
in_sign='ssssa{sas}ssss', out_sign='s',
method=self._set,
async=True)
host.bridge.addMethod("mergeRequestsSchemaGet", ".plugin",
@ -191,7 +191,7 @@ class MergeRequests(object):
defer.returnValue((tickets_xmlui, metadata, parsed_patches))
def _set(self, service, node, repository, method, values, schema=None, item_id=None,
extra=None, profile_key=C.PROF_KEY_NONE):
extra=u"", profile_key=C.PROF_KEY_NONE):
client, service, node, schema, item_id, extra = self._s.prepareBridgeSet(
service, node, schema, item_id, extra, profile_key)
d = self.set(client, service, node, repository, method, values, schema,

View file

@ -30,14 +30,14 @@ log = getLogger(__name__)
NS_TICKETS = "org.salut-a-toi.tickets:0"
PLUGIN_INFO = {
C.PI_NAME: _("Tickets management"),
C.PI_IMPORT_NAME: "TICKETS",
C.PI_TYPE: "EXP",
C.PI_NAME: _(u"Tickets management"),
C.PI_IMPORT_NAME: u"TICKETS",
C.PI_TYPE: u"EXP",
C.PI_PROTOCOLS: [],
C.PI_DEPENDENCIES: ["XEP-0060", "PUBSUB_SCHEMA", "XEP-0277", "IDENTITY"],
C.PI_MAIN: "Tickets",
C.PI_HANDLER: "no",
C.PI_DESCRIPTION: _("""Tickets management plugin"""),
C.PI_DEPENDENCIES: [u"XEP-0060", u"PUBSUB_SCHEMA", u"XEP-0277", u"IDENTITY"],
C.PI_MAIN: u"Tickets",
C.PI_HANDLER: u"no",
C.PI_DESCRIPTION: _(u"""Tickets management plugin"""),
}
@ -45,15 +45,15 @@ class Tickets(object):
def __init__(self, host):
log.info(_(u"Tickets plugin initialization"))
self.host = host
host.registerNamespace("tickets", NS_TICKETS)
self._p = self.host.plugins["XEP-0060"]
self._s = self.host.plugins["PUBSUB_SCHEMA"]
self._m = self.host.plugins["XEP-0277"]
host.registerNamespace(u"tickets", NS_TICKETS)
self._p = self.host.plugins[u"XEP-0060"]
self._s = self.host.plugins[u"PUBSUB_SCHEMA"]
self._m = self.host.plugins[u"XEP-0277"]
host.bridge.addMethod(
"ticketsGet",
".plugin",
in_sign="ssiassa{ss}s",
out_sign="(asa{ss})",
u"ticketsGet",
u".plugin",
in_sign=u"ssiassa{ss}s",
out_sign=u"(asa{ss})",
method=utils.partial(
self._s._get,
default_node=NS_TICKETS,
@ -69,7 +69,7 @@ class Tickets(object):
host.bridge.addMethod(
"ticketSet",
".plugin",
in_sign="ssa{sas}ssa{ss}s",
in_sign="ssa{sas}ssss",
out_sign="s",
method=self._set,
async=True,
@ -83,7 +83,7 @@ class Tickets(object):
async=True,
)
def _set(self, service, node, values, schema=None, item_id=None, extra=None,
def _set(self, service, node, values, schema=None, item_id=None, extra=u'',
profile_key=C.PROF_KEY_NONE):
client, service, node, schema, item_id, extra = self._s.prepareBridgeSet(
service, node, schema, item_id, extra, profile_key
@ -102,6 +102,7 @@ class Tickets(object):
@param node(unicode, None): Pubsub node to use
None to use default tickets node
@param values(dict[key(unicode), [iterable[object]|object]]): values of the ticket
if value is not iterable, it will be put in a list
'created' and 'updated' will be forced to current time:
- 'created' is set if item_id is None, i.e. if it's a new ticket
@ -114,6 +115,7 @@ class Tickets(object):
"""
if not node:
node = NS_TICKETS
if not item_id:
comments_service = yield self._m.getCommentsService(client, service)
@ -132,12 +134,13 @@ class Tickets(object):
self._p.OPT_PUBLISH_MODEL: self._p.ACCESS_OPEN,
}
yield self._p.createNode(client, comments_service, comments_node, options)
values["comments_uri"] = uri.buildXMPPUri(
values[u"comments_uri"] = uri.buildXMPPUri(
u"pubsub",
subtype="microblog",
path=comments_service.full(),
node=comments_node,
)
item_id = yield self._s.set(
client, service, node, values, schema, item_id, extra, deserialise, form_ns
)

View file

@ -20,6 +20,7 @@
import base
from sat.core.i18n import _
from sat.tools.common import data_format
from sat_frontends.jp.constants import Const as C
from sat_frontends.jp import xmlui_manager
from sat_frontends.jp import common
@ -80,7 +81,7 @@ class Set(base.CommandBase):
self.host.quit(C.EXIT_OK)
def sendRequest(self):
extra = {"update": "true"} if self.args.item else {}
extra = {"update": True} if self.args.item else {}
values = {}
if self.args.labels is not None:
values[u"labels"] = self.args.labels
@ -92,7 +93,7 @@ class Set(base.CommandBase):
values,
u"",
self.args.item,
extra,
data_format.serialise(extra),
self.profile,
callback=self.mergeRequestSetCb,
errback=partial(