plugins import, tickets import, bugzilla import: comments handling:

- comments are put in "comments" key in import data, it's a list of microblog data
- in resulting item, the comments uri is put in comments_uri field
- (plugin import) root_service and root_node are kept in session
- (plugin ticket) reporter name is now in "reporter" key instead of "reporter_name"
- (plugin bugizlla): if not reporter name is found, first part of email address is used
This commit is contained in:
Goffi 2017-10-20 08:48:41 +02:00
commit 08a14fa4ac
4 changed files with 50 additions and 19 deletions

View file

@ -53,8 +53,10 @@ class ImportPlugin(object):
@param import_handler(object): specialized import handler instance
must have the following methods:
- importItem: import a single main item (i.e. prepare data for publishing)
- importSubitems: import sub items (i.e. items linked to main item, e.g. comments). Must return a dict with kwargs for recursiveImport if items are to be imported. At east "items_import_data", "service" and "node" keys must be provided.
if None is returned, no subitems will be imported
- importSubitems: import sub items (i.e. items linked to main item, e.g. comments).
Must return a dict with kwargs for recursiveImport if items are to be imported recursively.
At least "items_import_data", "service" and "node" keys must be provided.
if None is returned, no recursion will be done to import subitems, but import can still be done directly by the method.
- publishItem: actualy publish an item
- itemFilters: modify item according to options
@param name(unicode): import handler name
@ -139,6 +141,7 @@ class ImportPlugin(object):
else:
if not value:
del options[opt_name]
try:
importer = import_handler.importers[name]
except KeyError:
@ -159,7 +162,10 @@ class ImportPlugin(object):
}
self.host.registerProgressCb(progress_id, partial(self.getProgress, import_handler), metadata, profile=client.profile)
self.host.bridge.progressStarted(progress_id, metadata, client.profile)
session = {} # session data, can be use by importers
session = { # session data, can be used by importers
u'root_service': pubsub_service,
u'root_node': pubsub_node
}
self.recursiveImport(client, import_handler, items_import_data, progress_id, session, options, None, pubsub_service, pubsub_node)
defer.returnValue(progress_id)
@ -172,6 +178,7 @@ class ImportPlugin(object):
@param progress_id(unicode): id of progression
@param session(dict): data for this import session
can be used by importer so store any useful data
"root_service" and "root_node" are set to the main pubsub service and node of the import
@param options(dict): import options
@param return_data(dict): data to return on progressFinished
@param service(jid.JID, None): PubSub service to use

View file

@ -19,16 +19,18 @@
from sat.core.i18n import _
from sat.core.constants import Const as C
from sat.core import exceptions
from sat.core.log import getLogger
log = getLogger(__name__)
from twisted.internet import defer
from sat.tools.common import uri
PLUGIN_INFO = {
C.PI_NAME: "tickets import",
C.PI_IMPORT_NAME: "TICKETS_IMPORT",
C.PI_TYPE: C.PLUG_TYPE_IMPORT,
C.PI_DEPENDENCIES: ["IMPORT", "XEP-0060", "PUBSUB_SCHEMA"],
C.PI_DEPENDENCIES: ["IMPORT", "XEP-0060", "XEP-0277", "PUBSUB_SCHEMA"],
C.PI_MAIN: "TicketsImportPlugin",
C.PI_HANDLER: "no",
C.PI_DESCRIPTION: _(u"""Tickets import management:
@ -47,6 +49,7 @@ class TicketsImportPlugin(object):
self.host = host
self._importers = {}
self._p = host.plugins['XEP-0060']
self._m = host.plugins['XEP-0277']
self._s = host.plugins['PUBSUB_SCHEMA']
host.plugins['IMPORT'].initialize(self, u'tickets')
@ -61,7 +64,8 @@ class TicketsImportPlugin(object):
'body': main description of the ticket
'creation': date of creation
'update': date of last update
'reporter_name': full name of reporter
'reporter': full name of reporter
'reporter_jid': jid of reporter
'reporter_email': email of reporter
'assigned_to_name': full name of person working on it
'assigned_to_email': email of person working on it
@ -79,13 +83,29 @@ class TicketsImportPlugin(object):
- "review": ticket is fixed and waiting for review
- "closed": ticket is finished or invalid
'milestone': target milestone for this ticket
'comments': list of microblog data (comment metadata, check [XEP_0277.send] data argument)
"""
if 'comments_uri' in item_import_data:
raise exceptions.DataError(_(u'comments_uri key will be generated and must not be used by importer'))
if session[u'root_node'] is None:
session[u'root_node'] = NS_TICKETS
if not 'schema' in session:
session['schema'] = yield self._s.getSchemaForm(client, service, node or NS_TICKETS)
session['schema'] = yield self._s.getSchemaForm(client, service, node or session[u'root_node'])
defer.returnValue(item_import_data)
@defer.inlineCallbacks
def importSubItems(self, client, item_import_data, ticket_data, session, options):
return None
# TODO: force "open" permission (except if private, check below)
# TODO: handle "private" metadata, to have non public access for node
comments = ticket_data.get('comments', [])
service, node = self._m.getCommentsService(client), self._m.getCommentsNode(session['root_node'] + u'_' + ticket_data['id'])
yield self._p.createIfNewNode(client, service, node)
ticket_data['comments_uri'] = uri.buildXMPPUri(u'pubsub', subtype='microblog', path=service.full(), node=node)
for comment in comments:
if 'updated' not in comment and 'published' in comment:
# we don't want an automatic update date
comment['updated'] = comment['published']
yield self._m.send(client, comment, service, node)
def publishItem(self, client, ticket_data, service, node, session):
if node is None:

View file

@ -26,6 +26,7 @@ from sat.core import exceptions
from twisted.internet import defer
import os.path
from lxml import etree
from sat.tools import utils
PLUGIN_INFO = {
@ -71,7 +72,12 @@ class BugzillaParser(object):
ticket['update'] = bug.findtext('delta_ts')
ticket['title'] = bug.findtext('short_desc')
reporter_elt = bug.find('reporter')
ticket['reporter_name'] = reporter_elt.get('name')
ticket['reporter'] = reporter_elt.get('name')
if ticket['reporter'] is None:
if '@' in reporter_elt.text:
ticket['reporter'] = reporter_elt.text[:reporter_elt.text.find('@')].title()
else:
ticket['reporter'] = u'no name'
ticket['reporter_email'] = reporter_elt.text
assigned_to_elt = bug.find('assigned_to')
ticket['assigned_to_name'] = assigned_to_elt.get('name')
@ -95,10 +101,11 @@ class BugzillaParser(object):
body = longdesc.findtext('thetext')
else:
who = longdesc.find('who')
comment = {'from': who.text,
'date': longdesc.findtext('bug_when'),
'nick': who.get('name'),
'body': longdesc.findtext('thetext')}
comment = {'id': longdesc.findtext('commentid'),
'author_email': who.text,
'published': utils.date_parse(longdesc.findtext('bug_when')),
'author': who.get('name', who.text),
'content': longdesc.findtext('thetext')}
comments.append(comment)
ticket['body'] = body

View file

@ -662,12 +662,9 @@ class XEP_0277(object):
@param access: Node access model, according to xep-0060 #4.5
@param profile_key: profile key
"""
# FIXME: check if this mehtod is needed, deprecate it if not
client = self.host.getClient(profile_key)
_jid, xmlstream = self.host.getJidNStream(profile_key)
if not _jid:
log.error(_(u"Can't find profile's jid"))
return
_options = {self._p.OPT_ACCESS_MODEL: access, self._p.OPT_PERSIST_ITEMS: 1, self._p.OPT_MAX_ITEMS: -1, self._p.OPT_DELIVER_PAYLOADS: 1, self._p.OPT_SEND_ITEM_SUBSCRIBE: 1}
def cb(result):
@ -683,17 +680,17 @@ class XEP_0277(object):
#If the node already exists, the condition is "conflict",
#else we have an unmanaged error
if s_error.value.condition == 'conflict':
#d = self.host.plugins["XEP-0060"].deleteNode(client, _jid.userhostJID(), NS_MICROBLOG)
#d = self.host.plugins["XEP-0060"].deleteNode(client, client.jid.userhostJID(), NS_MICROBLOG)
#d.addCallback(lambda x: create_node().addCallback(cb).addErrback(fatal_err))
change_node_options().addCallback(cb).addErrback(fatal_err)
else:
fatal_err(s_error)
def create_node():
return self._p.createNode(client, _jid.userhostJID(), NS_MICROBLOG, _options)
return self._p.createNode(client, client.jid.userhostJID(), NS_MICROBLOG, _options)
def change_node_options():
return self._p.setOptions(_jid.userhostJID(), NS_MICROBLOG, _jid.userhostJID(), _options, profile_key=profile_key)
return self._p.setOptions(client.jid.userhostJID(), NS_MICROBLOG, client.jid.userhostJID(), _options, profile_key=profile_key)
create_node().addCallback(cb).addErrback(err_cb)