def __run_executable(self, args, exe_path, prog_env, prog_cwd, runtime): process = psutil.Popen(args, executable=exe_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=prog_env, cwd=prog_cwd) def _msg(*text): print('[' + str(process.pid) + '] ', *text) # Run executable. stderr is redirected to stdout. _msg('RUNNING: ', safe_repr(exe_path), ', args: ', safe_repr(args)) # 'psutil' allows to use timeout in waiting for a subprocess. # If not timeout was specified then it is 'None' - no timeout, just waiting. # Runtime is useful mostly for interactive tests. try: timeout = runtime if runtime else _EXE_TIMEOUT stdout, stderr = process.communicate(timeout=timeout) retcode = process.returncode except (psutil.TimeoutExpired, subprocess.TimeoutExpired): if runtime: # When 'runtime' is set then expired timeout is a good sing # that the executable was running successfully for a specified time. # TODO Is there a better way return success than 'retcode = 0'? retcode = 0 else: # Exe is running and it is not interactive. Fail the test. retcode = 1 _msg('TIMED OUT!') # Kill the subprocess and its child processes. for p in list(process.children(recursive=True)) + [process]: with suppress(psutil.NoSuchProcess): p.kill() stdout, stderr = process.communicate() if is_py2: sys.stdout.write(stdout) sys.stderr.write(stderr) else: sys.stdout.buffer.write(stdout) sys.stderr.buffer.write(stderr) return retcode
def _run_executable(self, prog, args, run_from_path, runtime): """ Run executable created by PyInstaller. :param args: CLI options to pass to the created executable. """ # Run the test in a clean environment to make sure they're really self-contained. prog_env = copy.deepcopy(os.environ) prog_env['PATH'] = '' del prog_env['PATH'] # For Windows we need to keep minimal PATH for successful running of some tests. if is_win: # Minimum Windows PATH is in most cases: C:\Windows\system32;C:\Windows prog_env['PATH'] = os.pathsep.join(winutils.get_system_path()) exe_path = prog if(run_from_path): # Run executable in the temp directory # Add the directory containing the executable to $PATH # Basically, pretend we are a shell executing the program from $PATH. prog_cwd = self._tmpdir prog_name = os.path.basename(prog) prog_env['PATH'] = os.pathsep.join([prog_env.get('PATH', ''), os.path.dirname(prog)]) else: # Run executable in the directory where it is. prog_cwd = os.path.dirname(prog) # The executable will be called with argv[0] as relative not absolute path. prog_name = os.path.join(os.curdir, os.path.basename(prog)) # Workaround to enable win_codepage_test # If _distdir is 'bytes', PyI build fails with ASCII decode error # when it joins the 'bytes' _distdir with the 'unicode' filenames from bindep and # winmanifest. # # PyI succeeds with _distdir as 'unicode', but subprocess # fails with ASCII encode error. subprocess succeeds if progname is # mbcs-encoded 'bytes' if is_win and is_py2: if isinstance(exe_path, unicode): exe_path = exe_path.encode('mbcs') if isinstance(prog_name, unicode): prog_name = prog_name.encode('mbcs') if isinstance(prog_cwd, unicode): prog_cwd = prog_cwd.encode('mbcs') args = [prog_name] + args # Run executable. stderr is redirected to stdout. print('RUNNING: ', safe_repr(exe_path), ", args: ", safe_repr(args)) # Using sys.stdout/sys.stderr for subprocess fixes printing messages in # Windows command prompt. Py.test is then able to collect stdout/sterr # messages and display them if a test fails. process = psutil.Popen(args, executable=exe_path, stdout=sys.stdout, stderr=sys.stderr, env=prog_env, cwd=prog_cwd) # 'psutil' allows to use timeout in waiting for a subprocess. # If not timeout was specified then it is 'None' - no timeout, just waiting. # Runtime is useful mostly for interactive tests. try: timeout = runtime if runtime else _EXE_TIMEOUT retcode = process.wait(timeout=timeout) except psutil.TimeoutExpired: if runtime: # When 'runtime' is set then expired timeout is a good sing # that the executable was running successfully for a specified time. # TODO Is there a better way return success than 'retcode = 0'? retcode = 0 else: # Exe is still running and it is not an interactive test. Fail the test. retcode = 1 # Kill the subprocess and its child processes. for p in process.children(recursive=True): p.kill() process.kill() return retcode
def _run_executable(self, prog, args, run_from_path, runtime): """ Run executable created by PyInstaller. :param args: CLI options to pass to the created executable. """ # Run the test in a clean environment to make sure they're really self-contained. prog_env = copy.deepcopy(os.environ) prog_env['PATH'] = '' del prog_env['PATH'] # For Windows we need to keep minimal PATH for successful running of some tests. if is_win: # Minimum Windows PATH is in most cases: C:\Windows\system32;C:\Windows prog_env['PATH'] = os.pathsep.join(winutils.get_system_path()) exe_path = prog if (run_from_path): # Run executable in the temp directory # Add the directory containing the executable to $PATH # Basically, pretend we are a shell executing the program from $PATH. prog_cwd = self._tmpdir prog_name = os.path.basename(prog) prog_env['PATH'] = os.pathsep.join( [prog_env.get('PATH', ''), os.path.dirname(prog)]) else: # Run executable in the directory where it is. prog_cwd = os.path.dirname(prog) # The executable will be called with argv[0] as relative not absolute path. prog_name = os.path.join(os.curdir, os.path.basename(prog)) # Workaround to enable win_codepage_test # If _distdir is 'bytes', PyI build fails with ASCII decode error # when it joins the 'bytes' _distdir with the 'unicode' filenames from bindep and # winmanifest. # # PyI succeeds with _distdir as 'unicode', but subprocess # fails with ASCII encode error. subprocess succeeds if progname is # mbcs-encoded 'bytes' if is_win and is_py2: if isinstance(exe_path, unicode): exe_path = exe_path.encode('mbcs') if isinstance(prog_name, unicode): prog_name = prog_name.encode('mbcs') if isinstance(prog_cwd, unicode): prog_cwd = prog_cwd.encode('mbcs') args = [prog_name] + args # Run executable. stderr is redirected to stdout. print('RUNNING: ', safe_repr(exe_path), ", args: ", safe_repr(args)) # Using sys.stdout/sys.stderr for subprocess fixes printing messages in # Windows command prompt. Py.test is then able to collect stdout/sterr # messages and display them if a test fails. process = psutil.Popen(args, executable=exe_path, stdout=sys.stdout, stderr=sys.stderr, env=prog_env, cwd=prog_cwd) # 'psutil' allows to use timeout in waiting for a subprocess. # If not timeout was specified then it is 'None' - no timeout, just waiting. # Runtime is useful mostly for interactive tests. try: timeout = runtime if runtime else _EXE_TIMEOUT retcode = process.wait(timeout=timeout) except psutil.TimeoutExpired: if runtime: # When 'runtime' is set then expired timeout is a good sing # that the executable was running successfully for a specified time. # TODO Is there a better way return success than 'retcode = 0'? retcode = 0 else: # Exe is still running and it is not an interactive test. Fail the test. retcode = 1 # Kill the subprocess and its child processes. for p in process.children(recursive=True): p.kill() process.kill() return retcode
def _run_executable(self, prog, args, run_from_path, runtime): """ Run executable created by PyInstaller. :param args: CLI options to pass to the created executable. """ # Run the test in a clean environment to make sure they're really self-contained. prog_env = copy.deepcopy(os.environ) prog_env['PATH'] = '' del prog_env['PATH'] # For Windows we need to keep minimal PATH for successful running of some tests. if is_win: # Minimum Windows PATH is in most cases: C:\Windows\system32;C:\Windows prog_env['PATH'] = os.pathsep.join(winutils.get_system_path()) exe_path = prog if(run_from_path): # Run executable in the temp directory # Add the directory containing the executable to $PATH # Basically, pretend we are a shell executing the program from $PATH. prog_cwd = self._tmpdir prog_name = os.path.basename(prog) prog_env['PATH'] = os.pathsep.join([prog_env.get('PATH', ''), os.path.dirname(prog)]) else: # Run executable in the directory where it is. prog_cwd = os.path.dirname(prog) # The executable will be called with argv[0] as relative not absolute path. prog_name = os.path.join(os.curdir, os.path.basename(prog)) # Workaround to enable win_codepage_test # If _distdir is 'bytes', PyI build fails with ASCII decode error # when it joins the 'bytes' _distdir with the 'unicode' filenames from bindep and # winmanifest. # # PyI succeeds with _distdir as 'unicode', but subprocess # fails with ASCII encode error. subprocess succeeds if progname is # mbcs-encoded 'bytes' if is_win and is_py2: if isinstance(exe_path, unicode): exe_path = exe_path.encode('mbcs') if isinstance(prog_name, unicode): prog_name = prog_name.encode('mbcs') if isinstance(prog_cwd, unicode): prog_cwd = prog_cwd.encode('mbcs') args = [prog_name] + args # Run executable. stderr is redirected to stdout. print('RUNNING: ', safe_repr(exe_path), ", args: ", safe_repr(args)) # Using sys.stdout/sys.stderr for subprocess fixes printing messages in # Windows command prompt. Py.test is then able to collect stdout/sterr # messages and display them if a test fails. if is_py2: # Timeout keyword supported only in Python 3.3+ # TODO use module 'subprocess32' which implements timeout for Python 2.7. retcode = subprocess.call(args, executable=exe_path, stdout=sys.stdout, stderr=sys.stderr, env=prog_env, cwd=prog_cwd) else: try: retcode = subprocess.call(args, executable=exe_path, stdout=sys.stdout, stderr=sys.stderr, env=prog_env, cwd=prog_cwd, timeout=runtime) except subprocess.TimeoutExpired: # When 'timeout' is set then expired timeout is a good sing # that the executable was running successfully for a specified time. # TODO Is there a better way return success than 'retcode = 0'? retcode = 0 return retcode