comparison sat_frontends/jp/cmd_input.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.core import exceptions 23 from sat.core import exceptions
24 from sat_frontends.jp.constants import Const as C 24 from sat_frontends.jp.constants import Const as C
25 from sat.tools.common.ansi import ANSI as A 25 from sat.tools.common.ansi import ANSI as A
26 import subprocess 26 import subprocess
54 self._pos = [] 54 self._pos = []
55 self._values_ori = [] 55 self._values_ori = []
56 56
57 def add_parser_options(self): 57 def add_parser_options(self):
58 self.parser.add_argument( 58 self.parser.add_argument(
59 "--encoding", default="utf-8", help=_(u"encoding of the input data") 59 "--encoding", default="utf-8", help=_("encoding of the input data")
60 ) 60 )
61 self.parser.add_argument( 61 self.parser.add_argument(
62 "-i", 62 "-i",
63 "--stdin", 63 "--stdin",
64 action="append_const", 64 action="append_const",
65 const=(OPT_STDIN, None), 65 const=(OPT_STDIN, None),
66 dest="arguments", 66 dest="arguments",
67 help=_(u"standard input"), 67 help=_("standard input"),
68 ) 68 )
69 self.parser.add_argument( 69 self.parser.add_argument(
70 "-s", 70 "-s",
71 "--short", 71 "--short",
72 type=self.opt(OPT_SHORT), 72 type=self.opt(OPT_SHORT),
73 action="append", 73 action="append",
74 dest="arguments", 74 dest="arguments",
75 help=_(u"short option"), 75 help=_("short option"),
76 ) 76 )
77 self.parser.add_argument( 77 self.parser.add_argument(
78 "-l", 78 "-l",
79 "--long", 79 "--long",
80 type=self.opt(OPT_LONG), 80 type=self.opt(OPT_LONG),
81 action="append", 81 action="append",
82 dest="arguments", 82 dest="arguments",
83 help=_(u"long option"), 83 help=_("long option"),
84 ) 84 )
85 self.parser.add_argument( 85 self.parser.add_argument(
86 "-p", 86 "-p",
87 "--positional", 87 "--positional",
88 type=self.opt(OPT_POS), 88 type=self.opt(OPT_POS),
89 action="append", 89 action="append",
90 dest="arguments", 90 dest="arguments",
91 help=_(u"positional argument"), 91 help=_("positional argument"),
92 ) 92 )
93 self.parser.add_argument( 93 self.parser.add_argument(
94 "-x", 94 "-x",
95 "--ignore", 95 "--ignore",
96 action="append_const", 96 action="append_const",
97 const=(OPT_IGNORE, None), 97 const=(OPT_IGNORE, None),
98 dest="arguments", 98 dest="arguments",
99 help=_(u"ignore value"), 99 help=_("ignore value"),
100 ) 100 )
101 self.parser.add_argument( 101 self.parser.add_argument(
102 "-D", 102 "-D",
103 "--debug", 103 "--debug",
104 action="store_true", 104 action="store_true",
105 help=_(u"don't actually run commands but echo what would be launched"), 105 help=_("don't actually run commands but echo what would be launched"),
106 ) 106 )
107 self.parser.add_argument( 107 self.parser.add_argument(
108 "--log", type=argparse.FileType("wb"), help=_(u"log stdout to FILE") 108 "--log", type=argparse.FileType("wb"), help=_("log stdout to FILE")
109 ) 109 )
110 self.parser.add_argument( 110 self.parser.add_argument(
111 "--log-err", type=argparse.FileType("wb"), help=_(u"log stderr to FILE") 111 "--log-err", type=argparse.FileType("wb"), help=_("log stderr to FILE")
112 ) 112 )
113 self.parser.add_argument("command", nargs=argparse.REMAINDER) 113 self.parser.add_argument("command", nargs=argparse.REMAINDER)
114 114
115 def opt(self, type_): 115 def opt(self, type_):
116 return lambda s: (type_, s) 116 return lambda s: (type_, s)
121 arguments = self.args.arguments 121 arguments = self.args.arguments
122 try: 122 try:
123 arg_type, arg_name = arguments[self.args_idx] 123 arg_type, arg_name = arguments[self.args_idx]
124 except IndexError: 124 except IndexError:
125 self.disp( 125 self.disp(
126 _(u"arguments in input data and in arguments sequence don't match"), 126 _("arguments in input data and in arguments sequence don't match"),
127 error=True, 127 error=True,
128 ) 128 )
129 self.host.quit(C.EXIT_DATA_ERROR) 129 self.host.quit(C.EXIT_DATA_ERROR)
130 self.args_idx += 1 130 self.args_idx += 1
131 while self.args_idx < len(arguments): 131 while self.args_idx < len(arguments):
148 # we skip the whole row 148 # we skip the whole row
149 if self.args.debug: 149 if self.args.debug:
150 self.disp( 150 self.disp(
151 A.color( 151 A.color(
152 C.A_SUBHEADER, 152 C.A_SUBHEADER,
153 _(u"values: "), 153 _("values: "),
154 A.RESET, 154 A.RESET,
155 u", ".join(self._values_ori), 155 ", ".join(self._values_ori),
156 ), 156 ),
157 2, 157 2,
158 ) 158 )
159 self.disp(A.color(A.BOLD, _(u"**SKIPPING**\n"))) 159 self.disp(A.color(A.BOLD, _("**SKIPPING**\n")))
160 self.reset() 160 self.reset()
161 self.idx += 1 161 self.idx += 1
162 raise exceptions.CancelError 162 raise exceptions.CancelError
163 163
164 if not isinstance(value, list): 164 if not isinstance(value, list):
178 elif arg_type == OPT_IGNORE: 178 elif arg_type == OPT_IGNORE:
179 pass 179 pass
180 else: 180 else:
181 self.parser.error( 181 self.parser.error(
182 _( 182 _(
183 u"Invalid argument, an option type is expected, got {type_}:{name}" 183 "Invalid argument, an option type is expected, got {type_}:{name}"
184 ).format(type_=arg_type, name=arg_name) 184 ).format(type_=arg_type, name=arg_name)
185 ) 185 )
186 186
187 def runCommand(self): 187 def runCommand(self):
188 """run requested command with parsed arguments""" 188 """run requested command with parsed arguments"""
189 if self.args_idx != len(self.args.arguments): 189 if self.args_idx != len(self.args.arguments):
190 self.disp( 190 self.disp(
191 _(u"arguments in input data and in arguments sequence don't match"), 191 _("arguments in input data and in arguments sequence don't match"),
192 error=True, 192 error=True,
193 ) 193 )
194 self.host.quit(C.EXIT_DATA_ERROR) 194 self.host.quit(C.EXIT_DATA_ERROR)
195 self.disp( 195 self.disp(
196 A.color(C.A_HEADER, _(u"command {idx}").format(idx=self.idx)), 196 A.color(C.A_HEADER, _("command {idx}").format(idx=self.idx)),
197 no_lf=not self.args.debug, 197 no_lf=not self.args.debug,
198 ) 198 )
199 stdin = "".join(self._stdin) 199 stdin = "".join(self._stdin)
200 if self.args.debug: 200 if self.args.debug:
201 self.disp( 201 self.disp(
202 A.color( 202 A.color(
203 C.A_SUBHEADER, _(u"values: "), A.RESET, u", ".join(self._values_ori) 203 C.A_SUBHEADER, _("values: "), A.RESET, ", ".join(self._values_ori)
204 ), 204 ),
205 2, 205 2,
206 ) 206 )
207 207
208 if stdin: 208 if stdin:
209 self.disp(A.color(C.A_SUBHEADER, u"--- STDIN ---")) 209 self.disp(A.color(C.A_SUBHEADER, "--- STDIN ---"))
210 self.disp(stdin.decode("utf-8")) 210 self.disp(stdin)
211 self.disp(A.color(C.A_SUBHEADER, u"-------------")) 211 self.disp(A.color(C.A_SUBHEADER, "-------------"))
212 self.disp( 212 self.disp(
213 u"{indent}{prog} {static} {options} {positionals}".format( 213 "{indent}{prog} {static} {options} {positionals}".format(
214 indent=4 * u" ", 214 indent=4 * " ",
215 prog=sys.argv[0], 215 prog=sys.argv[0],
216 static=" ".join(self.args.command).decode("utf-8"), 216 static=" ".join(self.args.command),
217 options=u" ".join([o.decode("utf-8") for o in self._opts]), 217 options=" ".join([o for o in self._opts]),
218 positionals=u" ".join([p.decode("utf-8") for p in self._pos]), 218 positionals=" ".join([p for p in self._pos]),
219 ) 219 )
220 ) 220 )
221 self.disp(u"\n") 221 self.disp("\n")
222 else: 222 else:
223 self.disp(u" (" + u", ".join(self._values_ori) + u")", 2, no_lf=True) 223 self.disp(" (" + ", ".join(self._values_ori) + ")", 2, no_lf=True)
224 args = [sys.argv[0]] + self.args.command + self._opts + self._pos 224 args = [sys.argv[0]] + self.args.command + self._opts + self._pos
225 p = subprocess.Popen( 225 p = subprocess.Popen(
226 args, 226 args,
227 stdin=subprocess.PIPE, 227 stdin=subprocess.PIPE,
228 stdout=subprocess.PIPE, 228 stdout=subprocess.PIPE,
236 log.write(log_tpl.format(command=" ".join(args), buff=stdout)) 236 log.write(log_tpl.format(command=" ".join(args), buff=stdout))
237 if log_err: 237 if log_err:
238 log_err.write(log_tpl.format(command=" ".join(args), buff=stderr)) 238 log_err.write(log_tpl.format(command=" ".join(args), buff=stderr))
239 ret = p.wait() 239 ret = p.wait()
240 if ret == 0: 240 if ret == 0:
241 self.disp(A.color(C.A_SUCCESS, _(u"OK"))) 241 self.disp(A.color(C.A_SUCCESS, _("OK")))
242 else: 242 else:
243 self.disp(A.color(C.A_FAILURE, _(u"FAILED"))) 243 self.disp(A.color(C.A_FAILURE, _("FAILED")))
244 244
245 self.reset() 245 self.reset()
246 self.idx += 1 246 self.idx += 1
247 247
248 def filter(self, filter_type, filter_arg, value): 248 def filter(self, filter_type, filter_arg, value):
258 raise NotImplementedError 258 raise NotImplementedError
259 259
260 260
261 class Csv(InputCommon): 261 class Csv(InputCommon):
262 def __init__(self, host): 262 def __init__(self, host):
263 super(Csv, self).__init__(host, "csv", _(u"comma-separated values")) 263 super(Csv, self).__init__(host, "csv", _("comma-separated values"))
264 264
265 def add_parser_options(self): 265 def add_parser_options(self):
266 InputCommon.add_parser_options(self) 266 InputCommon.add_parser_options(self)
267 self.parser.add_argument( 267 self.parser.add_argument(
268 "-r", 268 "-r",
269 "--row", 269 "--row",
270 type=int, 270 type=int,
271 default=0, 271 default=0,
272 help=_(u"starting row (previous ones will be ignored)"), 272 help=_("starting row (previous ones will be ignored)"),
273 ) 273 )
274 self.parser.add_argument( 274 self.parser.add_argument(
275 "-S", 275 "-S",
276 "--split", 276 "--split",
277 action="append_const", 277 action="append_const",
278 const=("split", None), 278 const=("split", None),
279 dest="arguments", 279 dest="arguments",
280 help=_(u"split value in several options"), 280 help=_("split value in several options"),
281 ) 281 )
282 self.parser.add_argument( 282 self.parser.add_argument(
283 "-E", 283 "-E",
284 "--empty", 284 "--empty",
285 action="append", 285 action="append",
286 type=self.opt("empty"), 286 type=self.opt("empty"),
287 dest="arguments", 287 dest="arguments",
288 help=_(u"action to do on empty value ({choices})").format( 288 help=_("action to do on empty value ({choices})").format(
289 choices=u", ".join(OPT_EMPTY_CHOICES) 289 choices=", ".join(OPT_EMPTY_CHOICES)
290 ), 290 ),
291 ) 291 )
292 292
293 def filter(self, filter_type, filter_arg, value): 293 def filter(self, filter_type, filter_arg, value):
294 if filter_type == "split": 294 if filter_type == "split":
298 return value if value else None 298 return value if value else None
299 elif filter_arg == OPT_EMPTY_SKIP: 299 elif filter_arg == OPT_EMPTY_SKIP:
300 return value if value else False 300 return value if value else False
301 else: 301 else:
302 self.parser.error( 302 self.parser.error(
303 _(u"--empty value must be one of {choices}").format( 303 _("--empty value must be one of {choices}").format(
304 choices=u", ".join(OPT_EMPTY_CHOICES) 304 choices=", ".join(OPT_EMPTY_CHOICES)
305 ) 305 )
306 ) 306 )
307 307
308 super(Csv, self).filter(filter_type, filter_arg, value) 308 super(Csv, self).filter(filter_type, filter_arg, value)
309 309
329 def __init__(self, host): 329 def __init__(self, host):
330 super(Input, self).__init__( 330 super(Input, self).__init__(
331 host, 331 host,
332 "input", 332 "input",
333 use_profile=False, 333 use_profile=False,
334 help=_(u"launch command with external input"), 334 help=_("launch command with external input"),
335 ) 335 )