3458
|
1 #!/usr/bin/env python3 |
|
2 |
|
3 |
|
4 # jp: a SàT command line tool |
|
5 # Copyright (C) 2009-2020 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 json |
|
22 import os |
|
23 from sat.core.i18n import _ |
|
24 from sat.tools.common import data_format |
|
25 from sat_frontends.jp import common |
|
26 from sat_frontends.jp.constants import Const as C |
|
27 from . import base |
|
28 |
|
29 __commands__ = ["Ticket"] |
|
30 |
|
31 FIELDS_MAP = "mapping" |
|
32 |
|
33 |
|
34 class Get(base.CommandBase): |
|
35 def __init__(self, host): |
|
36 base.CommandBase.__init__( |
|
37 self, |
|
38 host, |
|
39 "get", |
|
40 use_verbose=True, |
|
41 use_pubsub=True, |
|
42 pubsub_flags={C.MULTI_ITEMS}, |
|
43 pubsub_defaults={"service": _("auto"), "node": _("auto")}, |
|
44 use_output=C.OUTPUT_LIST_XMLUI, |
|
45 help=_("get tickets"), |
|
46 ) |
|
47 |
|
48 def add_parser_options(self): |
|
49 pass |
|
50 |
|
51 async def start(self): |
|
52 await common.fill_well_known_uri(self, os.getcwd(), "tickets", meta_map={}) |
|
53 try: |
|
54 tickets_data = data_format.deserialise( |
|
55 await self.host.bridge.ticketsGet( |
|
56 self.args.service, |
|
57 self.args.node, |
|
58 self.args.max, |
|
59 self.args.items, |
|
60 "", |
|
61 self.getPubsubExtra(), |
|
62 self.profile, |
|
63 ), |
|
64 type_check=list |
|
65 ) |
|
66 except Exception as e: |
|
67 self.disp(f"can't get tickets: {e}", error=True) |
|
68 self.host.quit(C.EXIT_BRIDGE_ERRBACK) |
|
69 else: |
|
70 await self.output(tickets_data[0]) |
|
71 self.host.quit(C.EXIT_OK) |
|
72 |
|
73 |
|
74 class Import(base.CommandBase): |
|
75 # TODO: factorize with blog/import |
|
76 |
|
77 def __init__(self, host): |
|
78 super(Import, self).__init__( |
|
79 host, |
|
80 "import", |
|
81 use_progress=True, |
|
82 use_verbose=True, |
|
83 help=_("import tickets from external software/dataset"), |
|
84 ) |
|
85 |
|
86 def add_parser_options(self): |
|
87 self.parser.add_argument( |
|
88 "importer", |
|
89 nargs="?", |
|
90 help=_("importer name, nothing to display importers list"), |
|
91 ) |
|
92 self.parser.add_argument( |
|
93 "-o", |
|
94 "--option", |
|
95 action="append", |
|
96 nargs=2, |
|
97 default=[], |
|
98 metavar=("NAME", "VALUE"), |
|
99 help=_("importer specific options (see importer description)"), |
|
100 ) |
|
101 self.parser.add_argument( |
|
102 "-m", |
|
103 "--map", |
|
104 action="append", |
|
105 nargs=2, |
|
106 default=[], |
|
107 metavar=("IMPORTED_FIELD", "DEST_FIELD"), |
|
108 help=_( |
|
109 "specified field in import data will be put in dest field (default: use " |
|
110 "same field name, or ignore if it doesn't exist)" |
|
111 ), |
|
112 ) |
|
113 self.parser.add_argument( |
|
114 "-s", |
|
115 "--service", |
|
116 default="", |
|
117 metavar="PUBSUB_SERVICE", |
|
118 help=_("PubSub service where the items must be uploaded (default: server)"), |
|
119 ) |
|
120 self.parser.add_argument( |
|
121 "-n", |
|
122 "--node", |
|
123 default="", |
|
124 metavar="PUBSUB_NODE", |
|
125 help=_( |
|
126 "PubSub node where the items must be uploaded (default: tickets' " |
|
127 "defaults)" |
|
128 ), |
|
129 ) |
|
130 self.parser.add_argument( |
|
131 "location", |
|
132 nargs="?", |
|
133 help=_( |
|
134 "importer data location (see importer description), nothing to show " |
|
135 "importer description" |
|
136 ), |
|
137 ) |
|
138 |
|
139 async def onProgressStarted(self, metadata): |
|
140 self.disp(_("Tickets upload started"), 2) |
|
141 |
|
142 async def onProgressFinished(self, metadata): |
|
143 self.disp(_("Tickets uploaded successfully"), 2) |
|
144 |
|
145 async def onProgressError(self, error_msg): |
|
146 self.disp(_(f"Error while uploading tickets: {error_msg}"), error=True) |
|
147 |
|
148 async def start(self): |
|
149 if self.args.location is None: |
|
150 # no location, the list of importer or description is requested |
|
151 for name in ("option", "service", "node"): |
|
152 if getattr(self.args, name): |
|
153 self.parser.error( |
|
154 _(f"{name} argument can't be used without location argument")) |
|
155 if self.args.importer is None: |
|
156 self.disp( |
|
157 "\n".join( |
|
158 [ |
|
159 f"{name}: {desc}" |
|
160 for name, desc in await self.host.bridge.ticketsImportList() |
|
161 ] |
|
162 ) |
|
163 ) |
|
164 else: |
|
165 try: |
|
166 short_desc, long_desc = await self.host.bridge.ticketsImportDesc( |
|
167 self.args.importer |
|
168 ) |
|
169 except Exception as e: |
|
170 self.disp(f"can't get importer description: {e}", error=True) |
|
171 self.host.quit(C.EXIT_BRIDGE_ERRBACK) |
|
172 else: |
|
173 self.disp(f"{name}: {short_desc}\n\n{long_desc}") |
|
174 self.host.quit() |
|
175 else: |
|
176 # we have a location, an import is requested |
|
177 |
|
178 if self.args.progress: |
|
179 # we use a custom progress bar template as we want a counter |
|
180 self.pbar_template = [ |
|
181 _("Progress: "), ["Percentage"], " ", ["Bar"], " ", |
|
182 ["Counter"], " ", ["ETA"] |
|
183 ] |
|
184 |
|
185 options = {key: value for key, value in self.args.option} |
|
186 fields_map = dict(self.args.map) |
|
187 if fields_map: |
|
188 if FIELDS_MAP in options: |
|
189 self.parser.error( |
|
190 _("fields_map must be specified either preencoded in --option or " |
|
191 "using --map, but not both at the same time") |
|
192 ) |
|
193 options[FIELDS_MAP] = json.dumps(fields_map) |
|
194 |
|
195 try: |
|
196 progress_id = await self.host.bridge.ticketsImport( |
|
197 self.args.importer, |
|
198 self.args.location, |
|
199 options, |
|
200 self.args.service, |
|
201 self.args.node, |
|
202 self.profile, |
|
203 ) |
|
204 except Exception as e: |
|
205 self.disp( |
|
206 _(f"Error while trying to import tickets: {e}"), |
|
207 error=True, |
|
208 ) |
|
209 self.host.quit(C.EXIT_BRIDGE_ERRBACK) |
|
210 else: |
|
211 await self.set_progress_id(progress_id) |
|
212 |
|
213 |
|
214 class Ticket(base.CommandBase): |
|
215 subcommands = (Get, Import) |
|
216 |
|
217 def __init__(self, host): |
|
218 super(Ticket, self).__init__( |
|
219 host, "ticket", use_profile=False, help=_("tickets handling") |
|
220 ) |