comparison sat_frontends/jp/cmd_ticket.py @ 3028:ab2696e34d29

Python 3 port: /!\ this is a huge commit /!\ starting from this commit, SàT is needs Python 3.6+ /!\ SàT maybe be instable or some feature may not work anymore, this will improve with time This patch port backend, bridge and frontends to Python 3. Roughly this has been done this way: - 2to3 tools has been applied (with python 3.7) - all references to python2 have been replaced with python3 (notably shebangs) - fixed files not handled by 2to3 (notably the shell script) - several manual fixes - fixed issues reported by Python 3 that where not handled in Python 2 - replaced "async" with "async_" when needed (it's a reserved word from Python 3.7) - replaced zope's "implements" with @implementer decorator - temporary hack to handle data pickled in database, as str or bytes may be returned, to be checked later - fixed hash comparison for password - removed some code which is not needed anymore with Python 3 - deactivated some code which needs to be checked (notably certificate validation) - tested with jp, fixed reported issues until some basic commands worked - ported Primitivus (after porting dependencies like urwid satext) - more manual fixes
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 19:08:41 +0200
parents 003b8b4b56a7
children fee60f17ebac
comparison
equal deleted inserted replaced
3027:ff5bcb12ae60 3028:ab2696e34d29
16 16
17 # You should have received a copy of the GNU Affero General Public License 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/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19
20 20
21 import base 21 from . import base
22 from sat.core.i18n import _ 22 from sat.core.i18n import _
23 from sat_frontends.jp import common 23 from sat_frontends.jp import common
24 from sat_frontends.jp.constants import Const as C 24 from sat_frontends.jp.constants import Const as C
25 from functools import partial 25 from functools import partial
26 import json 26 import json
27 import os 27 import os
28 28
29 __commands__ = ["Ticket"] 29 __commands__ = ["Ticket"]
30 30
31 FIELDS_MAP = u"mapping" 31 FIELDS_MAP = "mapping"
32 32
33 33
34 class Get(base.CommandBase): 34 class Get(base.CommandBase):
35 def __init__(self, host): 35 def __init__(self, host):
36 base.CommandBase.__init__( 36 base.CommandBase.__init__(
38 host, 38 host,
39 "get", 39 "get",
40 use_verbose=True, 40 use_verbose=True,
41 use_pubsub=True, 41 use_pubsub=True,
42 pubsub_flags={C.MULTI_ITEMS}, 42 pubsub_flags={C.MULTI_ITEMS},
43 pubsub_defaults={u"service": _(u"auto"), u"node": _(u"auto")}, 43 pubsub_defaults={"service": _("auto"), "node": _("auto")},
44 use_output=C.OUTPUT_LIST_XMLUI, 44 use_output=C.OUTPUT_LIST_XMLUI,
45 help=_(u"get tickets"), 45 help=_("get tickets"),
46 ) 46 )
47 self.need_loop = True 47 self.need_loop = True
48 48
49 def add_parser_options(self): 49 def add_parser_options(self):
50 pass 50 pass
57 self.host.bridge.ticketsGet( 57 self.host.bridge.ticketsGet(
58 self.args.service, 58 self.args.service,
59 self.args.node, 59 self.args.node,
60 self.args.max, 60 self.args.max,
61 self.args.items, 61 self.args.items,
62 u"", 62 "",
63 self.getPubsubExtra(), 63 self.getPubsubExtra(),
64 self.profile, 64 self.profile,
65 callback=self.ticketsGetCb, 65 callback=self.ticketsGetCb,
66 errback=partial( 66 errback=partial(
67 self.errback, 67 self.errback,
68 msg=_(u"can't get tickets: {}"), 68 msg=_("can't get tickets: {}"),
69 exit_code=C.EXIT_BRIDGE_ERRBACK, 69 exit_code=C.EXIT_BRIDGE_ERRBACK,
70 ), 70 ),
71 ) 71 )
72 72
73 def start(self): 73 def start(self):
80 def __init__(self, host): 80 def __init__(self, host):
81 super(Import, self).__init__( 81 super(Import, self).__init__(
82 host, 82 host,
83 "import", 83 "import",
84 use_progress=True, 84 use_progress=True,
85 help=_(u"import tickets from external software/dataset"), 85 help=_("import tickets from external software/dataset"),
86 ) 86 )
87 self.need_loop = True 87 self.need_loop = True
88 88
89 def add_parser_options(self): 89 def add_parser_options(self):
90 self.parser.add_argument( 90 self.parser.add_argument(
91 "importer", 91 "importer",
92 type=base.unicode_decoder,
93 nargs="?", 92 nargs="?",
94 help=_(u"importer name, nothing to display importers list"), 93 help=_("importer name, nothing to display importers list"),
95 ) 94 )
96 self.parser.add_argument( 95 self.parser.add_argument(
97 "-o", 96 "-o",
98 "--option", 97 "--option",
99 action="append", 98 action="append",
100 nargs=2, 99 nargs=2,
101 default=[], 100 default=[],
102 metavar=(u"NAME", u"VALUE"), 101 metavar=("NAME", "VALUE"),
103 help=_(u"importer specific options (see importer description)"), 102 help=_("importer specific options (see importer description)"),
104 ) 103 )
105 self.parser.add_argument( 104 self.parser.add_argument(
106 "-m", 105 "-m",
107 "--map", 106 "--map",
108 action="append", 107 action="append",
109 nargs=2, 108 nargs=2,
110 default=[], 109 default=[],
111 metavar=(u"IMPORTED_FIELD", u"DEST_FIELD"), 110 metavar=("IMPORTED_FIELD", "DEST_FIELD"),
112 help=_( 111 help=_(
113 u"specified field in import data will be put in dest field (default: use same field name, or ignore if it doesn't exist)" 112 "specified field in import data will be put in dest field (default: use same field name, or ignore if it doesn't exist)"
114 ), 113 ),
115 ) 114 )
116 self.parser.add_argument( 115 self.parser.add_argument(
117 "-s", 116 "-s",
118 "--service", 117 "--service",
119 type=base.unicode_decoder, 118 default="",
120 default=u"", 119 metavar="PUBSUB_SERVICE",
121 metavar=u"PUBSUB_SERVICE", 120 help=_("PubSub service where the items must be uploaded (default: server)"),
122 help=_(u"PubSub service where the items must be uploaded (default: server)"),
123 ) 121 )
124 self.parser.add_argument( 122 self.parser.add_argument(
125 "-n", 123 "-n",
126 "--node", 124 "--node",
127 type=base.unicode_decoder, 125 default="",
128 default=u"", 126 metavar="PUBSUB_NODE",
129 metavar=u"PUBSUB_NODE",
130 help=_( 127 help=_(
131 u"PubSub node where the items must be uploaded (default: tickets' defaults)" 128 "PubSub node where the items must be uploaded (default: tickets' defaults)"
132 ), 129 ),
133 ) 130 )
134 self.parser.add_argument( 131 self.parser.add_argument(
135 "location", 132 "location",
136 type=base.unicode_decoder,
137 nargs="?", 133 nargs="?",
138 help=_( 134 help=_(
139 u"importer data location (see importer description), nothing to show importer description" 135 "importer data location (see importer description), nothing to show importer description"
140 ), 136 ),
141 ) 137 )
142 138
143 def onProgressStarted(self, metadata): 139 def onProgressStarted(self, metadata):
144 self.disp(_(u"Tickets upload started"), 2) 140 self.disp(_("Tickets upload started"), 2)
145 141
146 def onProgressFinished(self, metadata): 142 def onProgressFinished(self, metadata):
147 self.disp(_(u"Tickets uploaded successfully"), 2) 143 self.disp(_("Tickets uploaded successfully"), 2)
148 144
149 def onProgressError(self, error_msg): 145 def onProgressError(self, error_msg):
150 self.disp(_(u"Error while uploading tickets: {}").format(error_msg), error=True) 146 self.disp(_("Error while uploading tickets: {}").format(error_msg), error=True)
151 147
152 def error(self, failure): 148 def error(self, failure):
153 self.disp( 149 self.disp(
154 _("Error while trying to upload tickets: {reason}").format(reason=failure), 150 _("Error while trying to upload tickets: {reason}").format(reason=failure),
155 error=True, 151 error=True,
160 if self.args.location is None: 156 if self.args.location is None:
161 for name in ("option", "service", "node"): 157 for name in ("option", "service", "node"):
162 if getattr(self.args, name): 158 if getattr(self.args, name):
163 self.parser.error( 159 self.parser.error(
164 _( 160 _(
165 u"{name} argument can't be used without location argument" 161 "{name} argument can't be used without location argument"
166 ).format(name=name) 162 ).format(name=name)
167 ) 163 )
168 if self.args.importer is None: 164 if self.args.importer is None:
169 self.disp( 165 self.disp(
170 u"\n".join( 166 "\n".join(
171 [ 167 [
172 u"{}: {}".format(name, desc) 168 "{}: {}".format(name, desc)
173 for name, desc in self.host.bridge.ticketsImportList() 169 for name, desc in self.host.bridge.ticketsImportList()
174 ] 170 ]
175 ) 171 )
176 ) 172 )
177 else: 173 else:
178 try: 174 try:
179 short_desc, long_desc = self.host.bridge.ticketsImportDesc( 175 short_desc, long_desc = self.host.bridge.ticketsImportDesc(
180 self.args.importer 176 self.args.importer
181 ) 177 )
182 except Exception as e: 178 except Exception as e:
183 msg = [l for l in unicode(e).split("\n") if l][ 179 msg = [l for l in str(e).split("\n") if l][
184 -1 180 -1
185 ] # we only keep the last line 181 ] # we only keep the last line
186 self.disp(msg) 182 self.disp(msg)
187 self.host.quit(1) 183 self.host.quit(1)
188 else: 184 else:
189 self.disp( 185 self.disp(
190 u"{name}: {short_desc}\n\n{long_desc}".format( 186 "{name}: {short_desc}\n\n{long_desc}".format(
191 name=self.args.importer, 187 name=self.args.importer,
192 short_desc=short_desc, 188 short_desc=short_desc,
193 long_desc=long_desc, 189 long_desc=long_desc,
194 ) 190 )
195 ) 191 )
200 fields_map = dict(self.args.map) 196 fields_map = dict(self.args.map)
201 if fields_map: 197 if fields_map:
202 if FIELDS_MAP in options: 198 if FIELDS_MAP in options:
203 self.parser.error( 199 self.parser.error(
204 _( 200 _(
205 u"fields_map must be specified either preencoded in --option or using --map, but not both at the same time" 201 "fields_map must be specified either preencoded in --option or using --map, but not both at the same time"
206 ) 202 )
207 ) 203 )
208 options[FIELDS_MAP] = json.dumps(fields_map) 204 options[FIELDS_MAP] = json.dumps(fields_map)
209 205
210 def gotId(id_): 206 def gotId(id_):