def run_shell(*args, **kw): check_for_interrupt = kw.get('check_for_interrupt', False) create_process_group = kw.get('create_process_group', False) fail_silently = kw.get('fail_silently', False) command_log_level = kw.get("command_log_level", logging.DEBUG) filter = kw.get("filter", False) state = RunnerState() state.done = False state.output = StringIO.StringIO() state.proc = None state.error = None def runner(): try: preexec_fn = _required_preexec(create_process_group, os) state.proc = lib.PopenWithoutNewConsole(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=kw.get('env'), preexec_fn=preexec_fn) for line in iter(state.proc.stdout.readline, ''): if not filter or filter(line): state.output.write(line) LOG.log(command_log_level, line.rstrip('\r\n')) state.done = True except Exception as e: state.done = True state.error = e if check_for_interrupt: try: call = lib.current_call() runner_thread = threading.Thread(target=runner) runner_thread.daemon = True runner_thread.start() while not state.done: time.sleep(1) call.assert_not_interrupted() finally: # if interrupted, kill child process if state.proc and not state.done: lib.progressive_kill(state.proc.pid, kill_process_group=True) else: runner() if state.error: raise state.error if state.proc.wait() != 0: if fail_silently: LOG.debug('Failed to run %s, but was told to carry on anyway' % subprocess.list2cmdline(args)) else: raise ShellError( message="Failed when running {command}".format(command=args[0]), output=state.output.getvalue() ) return state.output.getvalue()
def run_iphone_simulator(self): if not sys.platform.startswith('darwin'): raise IOSError("iOS Simulator is only available on OS X, please change the iOS run settings in your local config.") possible_app_location = '{0}/ios/simulator-*/'.format(self.path_to_ios_build) LOG.debug('Looking for apps at {0}'.format(possible_app_location)) possible_apps = glob(possible_app_location) if not possible_apps: raise IOSError("Couldn't find iOS app to run it in the simulator") path_to_app = possible_apps[0] LOG.debug('trying to run app %s' % path_to_app) if path.exists(SIMULATOR_IN_42): LOG.debug("Detected XCode version 4.2 or older") ios_sim_binary = "ios-sim-xc4.2" elif path.exists(SIMULATOR_IN_43): LOG.debug("Detected XCode version 4.3 or newer") ios_sim_binary = "ios-sim-xc4.3" else: raise IOSError("Couldn't find iOS simulator in {old} or {new}".format( old=SIMULATOR_IN_42, new=SIMULATOR_IN_43, )) logfile = tempfile.mkstemp()[1] ios_sim_proc = subprocess.Popen([path.join(self._lib_path(), ios_sim_binary), "launch", path_to_app, '--stderr', logfile]) LOG.info('Showing log output:') try: run_shell("tail", "-f", logfile, fail_silently=False, command_log_level=logging.INFO, check_for_interrupt=True) finally: lib.progressive_kill(ios_sim_proc.pid) os.remove(logfile)
def run_shell(*args, **kw): check_for_interrupt = kw.get('check_for_interrupt', False) fail_silently = kw.get('fail_silently', False) command_log_level = kw.get("command_log_level", logging.DEBUG) filter = kw.get("filter", False) state = RunnerState() state.done = False state.output = StringIO.StringIO() state.proc = None def runner(): LOG.debug('Running: {cmd}'.format(cmd=subprocess.list2cmdline(args))) state.proc = lib.PopenWithoutNewConsole(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=kw.get('env')) for line in iter(state.proc.stdout.readline, ''): if not filter or filter(line): state.output.write(line) LOG.log(command_log_level, line.rstrip('\r\n')) state.done = True if check_for_interrupt: try: call = lib.current_call() runner_thread = threading.Thread(target=runner) runner_thread.daemon = True runner_thread.start() while not state.done: time.sleep(1) call.assert_not_interrupted() finally: # if interrupted, kill child process if state.proc and not state.done: lib.progressive_kill(state.proc.pid) else: runner() if state.proc.wait() != 0: if fail_silently: LOG.debug('Failed to run %s, but was told to carry on anyway' % subprocess.list2cmdline(args)) else: raise ShellError(message="Failed when running {command}".format( command=args[0]), output=state.output.getvalue()) return state.output.getvalue()
def run_iphone_simulator(self): if not sys.platform.startswith('darwin'): raise IOSError( "iOS Simulator is only available on OS X, please change the iOS run settings in your local config." ) possible_app_location = '{0}/ios/simulator-*/'.format( self.path_to_ios_build) LOG.debug('Looking for apps at {0}'.format(possible_app_location)) possible_apps = glob(possible_app_location) if not possible_apps: raise IOSError("Couldn't find iOS app to run it in the simulator") path_to_app = possible_apps[0] LOG.debug('trying to run app %s' % path_to_app) if path.exists(SIMULATOR_IN_42): LOG.debug("Detected XCode version 4.2 or older") ios_sim_binary = "ios-sim-xc4.2" elif path.exists(SIMULATOR_IN_43): LOG.debug("Detected XCode version 4.3 or newer") ios_sim_binary = "ios-sim-xc4.3" else: raise IOSError( "Couldn't find iOS simulator in {old} or {new}".format( old=SIMULATOR_IN_42, new=SIMULATOR_IN_43, )) logfile = tempfile.mkstemp()[1] ios_sim_proc = subprocess.Popen([ path.join(self._lib_path(), ios_sim_binary), "launch", path_to_app, '--stderr', logfile ]) LOG.info('Showing log output:') try: run_shell("tail", "-f", logfile, fail_silently=False, command_log_level=logging.INFO, check_for_interrupt=True) finally: lib.progressive_kill(ios_sim_proc.pid) os.remove(logfile)
def kill(self): import lib lib.progressive_kill(self._state.proc.pid)