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:
parent
363ee1db88
commit
08a14fa4ac
4 changed files with 50 additions and 19 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue