comparison sat_frontends/jp/cmd_ticket.py @ 2562:26edcf3a30eb

core, setup: huge cleaning: - moved directories from src and frontends/src to sat and sat_frontends, which is the recommanded naming convention - move twisted directory to root - removed all hacks from setup.py, and added missing dependencies, it is now clean - use https URL for website in setup.py - removed "Environment :: X11 Applications :: GTK", as wix is deprecated and removed - renamed sat.sh to sat and fixed its installation - added python_requires to specify Python version needed - replaced glib2reactor which use deprecated code by gtk3reactor sat can now be installed directly from virtualenv without using --system-site-packages anymore \o/
author Goffi <goffi@goffi.org>
date Mon, 02 Apr 2018 19:44:50 +0200
parents frontends/src/jp/cmd_ticket.py@0046283a285d
children 41db2f58c753
comparison
equal deleted inserted replaced
2561:bd30dc3ffe5a 2562:26edcf3a30eb
1 #!/usr/bin/env python2
2 # -*- coding: utf-8 -*-
3
4 # jp: a SàT command line tool
5 # Copyright (C) 2009-2018 Jérôme Poisson (goffi@goffi.org)
6
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
16
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
21 import base
22 from sat.core.i18n import _
23 import json
24
25 __commands__ = ["Ticket"]
26
27 FIELDS_MAP = u'mapping'
28
29
30 class Import(base.CommandAnswering):
31 # TODO: factorize with blog/import
32
33 def __init__(self, host):
34 super(Import, self).__init__(host, 'import', use_progress=True, help=_(u'import tickets from external software/dataset'))
35 self.need_loop=True
36
37 def add_parser_options(self):
38 self.parser.add_argument("importer", type=base.unicode_decoder, nargs='?', help=_(u"importer name, nothing to display importers list"))
39 self.parser.add_argument('-o', '--option', action='append', nargs=2, default=[], metavar=(u'NAME', u'VALUE'),
40 help=_(u"importer specific options (see importer description)"))
41 self.parser.add_argument('-m', '--map', action='append', nargs=2, default=[], metavar=(u'IMPORTED_FIELD', u'DEST_FIELD'),
42 help=_(u"specified field in import data will be put in dest field (default: use same field name, or ignore if it doesn't exist)"))
43 self.parser.add_argument('-s', '--service', type=base.unicode_decoder, default=u'', metavar=u'PUBSUB_SERVICE',
44 help=_(u"PubSub service where the items must be uploaded (default: server)"))
45 self.parser.add_argument('-n', '--node', type=base.unicode_decoder, default=u'', metavar=u'PUBSUB_NODE',
46 help=_(u"PubSub node where the items must be uploaded (default: tickets' defaults)"))
47 self.parser.add_argument("location", type=base.unicode_decoder, nargs='?',
48 help=_(u"importer data location (see importer description), nothing to show importer description"))
49
50 def onProgressStarted(self, metadata):
51 self.disp(_(u'Tickets upload started'),2)
52
53 def onProgressFinished(self, metadata):
54 self.disp(_(u'Tickets uploaded successfully'),2)
55
56 def onProgressError(self, error_msg):
57 self.disp(_(u'Error while uploading tickets: {}').format(error_msg),error=True)
58
59 def error(self, failure):
60 self.disp(_("Error while trying to upload tickets: {reason}").format(reason=failure), error=True)
61 self.host.quit(1)
62
63 def start(self):
64 if self.args.location is None:
65 for name in ('option', 'service', 'node'):
66 if getattr(self.args, name):
67 self.parser.error(_(u"{name} argument can't be used without location argument").format(name=name))
68 if self.args.importer is None:
69 self.disp(u'\n'.join([u'{}: {}'.format(name, desc) for name, desc in self.host.bridge.ticketsImportList()]))
70 else:
71 try:
72 short_desc, long_desc = self.host.bridge.ticketsImportDesc(self.args.importer)
73 except Exception as e:
74 msg = [l for l in unicode(e).split('\n') if l][-1] # we only keep the last line
75 self.disp(msg)
76 self.host.quit(1)
77 else:
78 self.disp(u"{name}: {short_desc}\n\n{long_desc}".format(name=self.args.importer, short_desc=short_desc, long_desc=long_desc))
79 self.host.quit()
80 else:
81 # we have a location, an import is requested
82 options = {key: value for key, value in self.args.option}
83 fields_map = dict(self.args.map)
84 if fields_map:
85 if FIELDS_MAP in options:
86 self.parser.error(_(u"fields_map must be specified either preencoded in --option or using --map, but not both at the same time"))
87 options[FIELDS_MAP] = json.dumps(fields_map)
88 def gotId(id_):
89 self.progress_id = id_
90 self.host.bridge.ticketsImport(self.args.importer, self.args.location, options, self.args.service, self.args.node, self.profile,
91 callback=gotId, errback=self.error)
92
93
94 class Ticket(base.CommandBase):
95 subcommands = (Import,)
96
97 def __init__(self, host):
98 super(Ticket, self).__init__(host, 'ticket', use_profile=False, help=_('tickets handling'))