comparison sat/plugins/plugin_tickets_import.py @ 2624:56f94936df1e

code style reformatting using black
author Goffi <goffi@goffi.org>
date Wed, 27 Jun 2018 20:14:46 +0200
parents 26edcf3a30eb
children 003b8b4b56a7
comparison
equal deleted inserted replaced
2623:49533de4540b 2624:56f94936df1e
19 19
20 from sat.core.i18n import _ 20 from sat.core.i18n import _
21 from sat.core.constants import Const as C 21 from sat.core.constants import Const as C
22 from sat.core import exceptions 22 from sat.core import exceptions
23 from sat.core.log import getLogger 23 from sat.core.log import getLogger
24
24 log = getLogger(__name__) 25 log = getLogger(__name__)
25 from twisted.internet import defer 26 from twisted.internet import defer
26 from sat.tools.common import uri 27 from sat.tools.common import uri
27 from sat.tools import utils 28 from sat.tools import utils
28 29
32 C.PI_IMPORT_NAME: "TICKETS_IMPORT", 33 C.PI_IMPORT_NAME: "TICKETS_IMPORT",
33 C.PI_TYPE: C.PLUG_TYPE_IMPORT, 34 C.PI_TYPE: C.PLUG_TYPE_IMPORT,
34 C.PI_DEPENDENCIES: ["IMPORT", "XEP-0060", "XEP-0277", "PUBSUB_SCHEMA"], 35 C.PI_DEPENDENCIES: ["IMPORT", "XEP-0060", "XEP-0277", "PUBSUB_SCHEMA"],
35 C.PI_MAIN: "TicketsImportPlugin", 36 C.PI_MAIN: "TicketsImportPlugin",
36 C.PI_HANDLER: "no", 37 C.PI_HANDLER: "no",
37 C.PI_DESCRIPTION: _(u"""Tickets import management: 38 C.PI_DESCRIPTION: _(
38 This plugin manage the different tickets importers which can register to it, and handle generic importing tasks.""") 39 u"""Tickets import management:
40 This plugin manage the different tickets importers which can register to it, and handle generic importing tasks."""
41 ),
39 } 42 }
40 43
41 OPT_MAPPING = 'mapping' 44 OPT_MAPPING = "mapping"
42 FIELDS_LIST = (u'labels', u'cc_emails') # fields which must have a list as value 45 FIELDS_LIST = (u"labels", u"cc_emails") # fields which must have a list as value
43 FIELDS_DATE = (u'created', u'updated') 46 FIELDS_DATE = (u"created", u"updated")
44 47
45 NS_TICKETS = 'org.salut-a-toi.tickets:0' 48 NS_TICKETS = "org.salut-a-toi.tickets:0"
46 49
47 50
48 class TicketsImportPlugin(object): 51 class TicketsImportPlugin(object):
49 BOOL_OPTIONS = () 52 BOOL_OPTIONS = ()
50 JSON_OPTIONS = (OPT_MAPPING,) 53 JSON_OPTIONS = (OPT_MAPPING,)
52 55
53 def __init__(self, host): 56 def __init__(self, host):
54 log.info(_("plugin Tickets Import initialization")) 57 log.info(_("plugin Tickets Import initialization"))
55 self.host = host 58 self.host = host
56 self._importers = {} 59 self._importers = {}
57 self._p = host.plugins['XEP-0060'] 60 self._p = host.plugins["XEP-0060"]
58 self._m = host.plugins['XEP-0277'] 61 self._m = host.plugins["XEP-0277"]
59 self._s = host.plugins['PUBSUB_SCHEMA'] 62 self._s = host.plugins["PUBSUB_SCHEMA"]
60 host.plugins['IMPORT'].initialize(self, u'tickets') 63 host.plugins["IMPORT"].initialize(self, u"tickets")
61 64
62 @defer.inlineCallbacks 65 @defer.inlineCallbacks
63 def importItem(self, client, item_import_data, session, options, return_data, service, node): 66 def importItem(
67 self, client, item_import_data, session, options, return_data, service, node
68 ):
64 """ 69 """
65 70
66 @param item_import_data(dict): no key is mandatory, but if a key doesn't exists in dest form, it will be ignored. 71 @param item_import_data(dict): no key is mandatory, but if a key doesn't exists in dest form, it will be ignored.
67 Following names are recommendations which should be used where suitable in importers. 72 Following names are recommendations which should be used where suitable in importers.
68 except if specified in description, values are unicode 73 except if specified in description, values are unicode
99 e.g.: if you want to map "component" to "labels", you can specify: 104 e.g.: if you want to map "component" to "labels", you can specify:
100 {'component': 'labels'} 105 {'component': 'labels'}
101 If you specify several import ticket key to the same dest key, 106 If you specify several import ticket key to the same dest key,
102 the values will be joined with line feeds 107 the values will be joined with line feeds
103 """ 108 """
104 if 'comments_uri' in item_import_data: 109 if "comments_uri" in item_import_data:
105 raise exceptions.DataError(_(u'comments_uri key will be generated and must not be used by importer')) 110 raise exceptions.DataError(
111 _(u"comments_uri key will be generated and must not be used by importer")
112 )
106 for key in FIELDS_LIST: 113 for key in FIELDS_LIST:
107 if not isinstance(item_import_data.get(key, []), list): 114 if not isinstance(item_import_data.get(key, []), list):
108 raise exceptions.DataError(_(u'{key} must be a list').format(key=key)) 115 raise exceptions.DataError(_(u"{key} must be a list").format(key=key))
109 for key in FIELDS_DATE: 116 for key in FIELDS_DATE:
110 try: 117 try:
111 item_import_data[key] = utils.xmpp_date(item_import_data[key]) 118 item_import_data[key] = utils.xmpp_date(item_import_data[key])
112 except KeyError: 119 except KeyError:
113 continue 120 continue
114 if session[u'root_node'] is None: 121 if session[u"root_node"] is None:
115 session[u'root_node'] = NS_TICKETS 122 session[u"root_node"] = NS_TICKETS
116 if not 'schema' in session: 123 if not "schema" in session:
117 session['schema'] = yield self._s.getSchemaForm(client, service, node or session[u'root_node']) 124 session["schema"] = yield self._s.getSchemaForm(
125 client, service, node or session[u"root_node"]
126 )
118 defer.returnValue(item_import_data) 127 defer.returnValue(item_import_data)
119 128
120 @defer.inlineCallbacks 129 @defer.inlineCallbacks
121 def importSubItems(self, client, item_import_data, ticket_data, session, options): 130 def importSubItems(self, client, item_import_data, ticket_data, session, options):
122 # TODO: force "open" permission (except if private, check below) 131 # TODO: force "open" permission (except if private, check below)
123 # TODO: handle "private" metadata, to have non public access for node 132 # TODO: handle "private" metadata, to have non public access for node
124 # TODO: node access/publish model should be customisable 133 # TODO: node access/publish model should be customisable
125 comments = ticket_data.get('comments', []) 134 comments = ticket_data.get("comments", [])
126 service = yield self._m.getCommentsService(client) 135 service = yield self._m.getCommentsService(client)
127 node = self._m.getCommentsNode(session['root_node'] + u'_' + ticket_data['id']) 136 node = self._m.getCommentsNode(session["root_node"] + u"_" + ticket_data["id"])
128 node_options = {self._p.OPT_ACCESS_MODEL: self._p.ACCESS_OPEN, 137 node_options = {
129 self._p.OPT_PERSIST_ITEMS: 1, 138 self._p.OPT_ACCESS_MODEL: self._p.ACCESS_OPEN,
130 self._p.OPT_MAX_ITEMS: -1, 139 self._p.OPT_PERSIST_ITEMS: 1,
131 self._p.OPT_DELIVER_PAYLOADS: 1, 140 self._p.OPT_MAX_ITEMS: -1,
132 self._p.OPT_SEND_ITEM_SUBSCRIBE: 1, 141 self._p.OPT_DELIVER_PAYLOADS: 1,
133 self._p.OPT_PUBLISH_MODEL: self._p.ACCESS_OPEN, 142 self._p.OPT_SEND_ITEM_SUBSCRIBE: 1,
134 } 143 self._p.OPT_PUBLISH_MODEL: self._p.ACCESS_OPEN,
144 }
135 yield self._p.createIfNewNode(client, service, node, options=node_options) 145 yield self._p.createIfNewNode(client, service, node, options=node_options)
136 ticket_data['comments_uri'] = uri.buildXMPPUri(u'pubsub', subtype='microblog', path=service.full(), node=node) 146 ticket_data["comments_uri"] = uri.buildXMPPUri(
147 u"pubsub", subtype="microblog", path=service.full(), node=node
148 )
137 for comment in comments: 149 for comment in comments:
138 if 'updated' not in comment and 'published' in comment: 150 if "updated" not in comment and "published" in comment:
139 # we don't want an automatic update date 151 # we don't want an automatic update date
140 comment['updated'] = comment['published'] 152 comment["updated"] = comment["published"]
141 yield self._m.send(client, comment, service, node) 153 yield self._m.send(client, comment, service, node)
142 154
143 def publishItem(self, client, ticket_data, service, node, session): 155 def publishItem(self, client, ticket_data, service, node, session):
144 if node is None: 156 if node is None:
145 node = NS_TICKETS 157 node = NS_TICKETS
146 id_ = ticket_data.pop('id', None) 158 id_ = ticket_data.pop("id", None)
147 log.debug(u"uploading item [{id}]: {title}".format(id=id_, title=ticket_data.get('title',''))) 159 log.debug(
148 return self._s.sendDataFormItem(client, service, node, ticket_data, session['schema'], id_) 160 u"uploading item [{id}]: {title}".format(
161 id=id_, title=ticket_data.get("title", "")
162 )
163 )
164 return self._s.sendDataFormItem(
165 client, service, node, ticket_data, session["schema"], id_
166 )
149 167
150 def itemFilters(self, client, ticket_data, session, options): 168 def itemFilters(self, client, ticket_data, session, options):
151 mapping = options.get(OPT_MAPPING) 169 mapping = options.get(OPT_MAPPING)
152 if mapping is not None: 170 if mapping is not None:
153 if not isinstance(mapping, dict): 171 if not isinstance(mapping, dict):
154 raise exceptions.DataError(_(u'mapping option must be a dictionary')) 172 raise exceptions.DataError(_(u"mapping option must be a dictionary"))
155 173
156 for source, dest in mapping.iteritems(): 174 for source, dest in mapping.iteritems():
157 if not isinstance(source, unicode) or not isinstance(dest, unicode): 175 if not isinstance(source, unicode) or not isinstance(dest, unicode):
158 raise exceptions.DataError(_(u'keys and values of mapping must be sources and destinations ticket fields')) 176 raise exceptions.DataError(
177 _(
178 u"keys and values of mapping must be sources and destinations ticket fields"
179 )
180 )
159 if source in ticket_data: 181 if source in ticket_data:
160 value = ticket_data.pop(source) 182 value = ticket_data.pop(source)
161 if dest in FIELDS_LIST: 183 if dest in FIELDS_LIST:
162 values = ticket_data[dest] = ticket_data.get(dest, []) 184 values = ticket_data[dest] = ticket_data.get(dest, [])
163 values.append(value) 185 values.append(value)
164 else: 186 else:
165 if dest in ticket_data: 187 if dest in ticket_data:
166 ticket_data[dest] = ticket_data[dest] + u'\n' + value 188 ticket_data[dest] = ticket_data[dest] + u"\n" + value
167 else: 189 else:
168 ticket_data[dest] = value 190 ticket_data[dest] = value