plugins tickets import, jp (ticket/import): implemented mapping:
- mapping is an option allowing do map imported field to a specific field in the newly created item - importers can now use complexe data types in options using JSON
This commit is contained in:
parent
baaa4b1419
commit
55a5b603fd
3 changed files with 53 additions and 5 deletions
|
|
@ -54,6 +54,7 @@ URL_REDIRECT_PREFIX = 'url_redirect_'
|
|||
|
||||
class BlogImportPlugin(object):
|
||||
BOOL_OPTIONS = (OPT_UPLOAD_IMAGES, OPT_IGNORE_TLS)
|
||||
JSON_OPTIONS = ()
|
||||
OPT_DEFAULTS = {OPT_UPLOAD_IMAGES: True,
|
||||
OPT_IGNORE_TLS: False}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ from sat.core import exceptions
|
|||
from functools import partial
|
||||
import collections
|
||||
import uuid
|
||||
import json
|
||||
|
||||
|
||||
PLUGIN_INFO = {
|
||||
|
|
@ -110,6 +111,11 @@ class ImportPlugin(object):
|
|||
options[option] = C.bool(options[option])
|
||||
except KeyError:
|
||||
pass
|
||||
for option in import_handler.JSON_OPTIONS:
|
||||
try:
|
||||
options[option] = json.loads(options[option])
|
||||
except ValueError:
|
||||
raise exceptions.DataError(_(u'invalid json option: {name}').format(name=option))
|
||||
return self.doImport(client, import_handler, unicode(name), unicode(location), options, pubsub_service or None, pubsub_node or None)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ from sat.core.log import getLogger
|
|||
log = getLogger(__name__)
|
||||
from twisted.internet import defer
|
||||
from sat.tools.common import uri
|
||||
from sat.tools import utils
|
||||
|
||||
|
||||
PLUGIN_INFO = {
|
||||
|
|
@ -37,11 +38,16 @@ PLUGIN_INFO = {
|
|||
This plugin manage the different tickets importers which can register to it, and handle generic importing tasks.""")
|
||||
}
|
||||
|
||||
OPT_MAPPING = 'mapping'
|
||||
FIELDS_LIST = (u'labels', u'cc_emails') # fields which must have a list as value
|
||||
FIELDS_DATE = (u'created', u'updated')
|
||||
|
||||
NS_TICKETS = 'org.salut-a-toi.tickets:0'
|
||||
|
||||
|
||||
class TicketsImportPlugin(object):
|
||||
BOOL_OPTIONS = ()
|
||||
JSON_OPTIONS = (OPT_MAPPING,)
|
||||
OPT_DEFAULTS = {}
|
||||
|
||||
def __init__(self, host):
|
||||
|
|
@ -59,19 +65,21 @@ class TicketsImportPlugin(object):
|
|||
|
||||
@param item_import_data(dict): no key is mandatory, but if a key doesn't exists in dest form, it will be ignored.
|
||||
Following names are recommendations which should be used where suitable in importers.
|
||||
except if specified in description, values are unicode
|
||||
'id': unique id (must be unique in the node) of the ticket
|
||||
'title': title (or short description/summary) of the ticket
|
||||
'body': main description of the ticket
|
||||
'creation': date of creation
|
||||
'update': date of last update
|
||||
'created': date of creation (unix time)
|
||||
'updated': date of last update (unix time)
|
||||
'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
|
||||
'cc_emails': iterable of emails subscribed to the ticket
|
||||
'cc_emails': list of emails subscribed to the ticket
|
||||
'priority': priority of the ticket
|
||||
'severity': severity of the ticket
|
||||
'labels': list of unicode values to use as label
|
||||
'product': product concerned by this ticket
|
||||
'component': part of the product concerned by this ticket
|
||||
'version': version of the product/component concerned by this ticket
|
||||
|
|
@ -84,9 +92,25 @@ class TicketsImportPlugin(object):
|
|||
- "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)
|
||||
@param options(dict, None): Below are the generic options,
|
||||
tickets importer can have specific ones. All options are serialized unicode values
|
||||
generic options:
|
||||
- OPT_MAPPING (json): dict of imported ticket key => exported ticket key
|
||||
e.g.: if you want to map "component" to "labels", you can specify:
|
||||
{'component': 'labels'}
|
||||
If you specify several import ticket key to the same dest key,
|
||||
the values will be joined with line feeds
|
||||
"""
|
||||
if 'comments_uri' in item_import_data:
|
||||
raise exceptions.DataError(_(u'comments_uri key will be generated and must not be used by importer'))
|
||||
for key in FIELDS_LIST:
|
||||
if not isinstance(item_import_data.get(key, []), list):
|
||||
raise exceptions.DataError(_(u'{key} must be a list').format(key=key))
|
||||
for key in FIELDS_DATE:
|
||||
try:
|
||||
item_import_data[key] = utils.xmpp_date(item_import_data[key])
|
||||
except KeyError:
|
||||
continue
|
||||
if session[u'root_node'] is None:
|
||||
session[u'root_node'] = NS_TICKETS
|
||||
if not 'schema' in session:
|
||||
|
|
@ -123,4 +147,21 @@ class TicketsImportPlugin(object):
|
|||
return self._s.sendDataFormItem(client, service, node, ticket_data, session['schema'], id_)
|
||||
|
||||
def itemFilters(self, client, ticket_data, session, options):
|
||||
return None
|
||||
mapping = options.get(OPT_MAPPING)
|
||||
if mapping is not None:
|
||||
if not isinstance(mapping, dict):
|
||||
raise exceptions.DataError(_(u'mapping option must be a dictionary'))
|
||||
|
||||
for source, dest in mapping.iteritems():
|
||||
if not isinstance(source, unicode) or not isinstance(dest, unicode):
|
||||
raise exceptions.DataError(_(u'keys and values of mapping must be sources and destinations ticket fields'))
|
||||
if source in ticket_data:
|
||||
value = ticket_data.pop(source)
|
||||
if dest in FIELDS_LIST:
|
||||
values = ticket_data[dest] = ticket_data.get(dest, [])
|
||||
values.append(value)
|
||||
else:
|
||||
if dest in ticket_data:
|
||||
ticket_data[dest] = ticket_data[dest] + u'\n' + value
|
||||
else:
|
||||
ticket_data[dest] = value
|
||||
|
|
|
|||
Loading…
Reference in a new issue