Mercurial > libervia-backend
diff frontends/src/jp/cmd_shell.py @ 2313:6ff5212997c7
jp (shell): use of subprocess instead of running commands in the same process:
when a command is calling host.quit() in a D-Bus callback, GLib mainloop is exiting and quit the whole process without (apparently?) any way to block it. Couldn't find a good way to avoid that, so subprocess are now used as a workaround, instead of launching commands in the same process. When we'll get rid of python-dbus, there may be an other way.
Execuring external commands is now possible through the shell/! command.
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 07 Jul 2017 22:33:55 +0200 |
parents | a42a2478abd2 |
children | 8d9bd5d77336 |
line wrap: on
line diff
--- a/frontends/src/jp/cmd_shell.py Fri Jul 07 12:45:28 2017 +0200 +++ b/frontends/src/jp/cmd_shell.py Fri Jul 07 22:33:55 2017 +0200 @@ -20,11 +20,13 @@ import base import cmd +import sys from sat.core.i18n import _ from sat.core import exceptions from sat_frontends.jp.constants import Const as C from sat.tools.common.ansi import ANSI as A import shlex +import subprocess __commands__ = ["Shell"] INTRO = _(u"""Welcome to {app_name} shell, the Salut à Toi shell ! @@ -98,7 +100,7 @@ # else USE args would not work correctly (only for current parser) cmd_args = [] for arg in args: - if arg.startswith(u'-'): + if arg.startswith('-'): break try: parser = self.get_cmd_choices(arg, parser) @@ -131,6 +133,43 @@ opt_args.append(value) return cmd_args + opt_args + pos_args + def run_cmd(self, args, external=False): + """run command and retur exit code + + @param args[list[string]]: arguments of the command + must not include program name + @param external(bool): True if it's an external command (i.e. not jp) + @return (int): exit code (0 success, any other int failure) + """ + # FIXME: we have to use subprocess + # and relaunch whole python for now + # because if host.quit() is called in D-Bus callback + # GLib quit the whole app without possibility to stop it + # didn't found a nice way to work around it so far + # Situation should be better when we'll move away from python-dbus + if self.verbose: + self.disp(_(u"COMMAND {external}=> {args}").format( + external = _(u'(external) ') if external else u'', + args=u' '.join(self.format_args(args)))) + if not external: + args = sys.argv[0:1] + args + ret_code= subprocess.call(args) + # XXX: below is a way to launch the command without creating a new process + # may be used when a solution to the aforementioned issue is there + # try: + # self.host.run(args) + # except SystemExit as e: + # ret_code = e.code + # except Exception as e: + # self.disp(A.color(C.A_FAILURE, u'command failed with an exception: {msg}'.format(msg=e)), error=True) + # ret_code = 1 + # else: + # ret_code = 0 + + if ret_code != 0: + self.disp(A.color(C.A_FAILURE, u'command failed with an error code of {err_no}'.format(err_no=ret_code)), error=True) + return ret_code + def default(self, args): """called when no shell command is recognized @@ -187,27 +226,19 @@ except SystemExit: pass + def do_shell(self, args): + """launch an external command (you can use ![command] too)""" + args = self.parse_args(args) + self.run_cmd(args, external=True) + def do_do(self, args): """lauch a command""" - # we don't want host to really exit - # we want to stay in the loop - self.host._no_exit = True args = self.parse_args(args) # args may be modified by use_args # to remove subparsers from it use_args = self.get_use_args(args) cmd_args = self.path + use_args + args - if self.verbose: - self.disp(u"COMMAND => {args}".format(args=u' '.join(self.format_args(cmd_args)))) - try: - self.host.run(cmd_args) - except SystemExit as e: - if e.code != 0: - self.disp(A.color(C.A_FAILURE, u'command failed with an error code of {err_no}'.format(err_no=e.code)), error=True) - except Exception as e: - self.disp(A.color(C.A_FAILURE, u'command failed with an exception: {msg}'.format(msg=e)), error=True) - finally: - self.host._no_exit = False + self.run_cmd(cmd_args) def do_use(self, args): """fix an argument"""