plugins schema, tickets, merge_requests: use serialised data for extra dict + some cosmetic changes
This commit is contained in:
parent
0f97a75f6f
commit
481ce4c379
5 changed files with 94 additions and 72 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Reference in a new issue