def execute(cmd, directory=os.getcwd(), capture=False, stdout_file=None, stderr_file=None, allow_fail=False): """A simple wrapper around executor.""" from executor import ExternalCommand, ExternalCommandFailed try: command = ExternalCommand(cmd, directory=directory, capture=True, capture_stderr=True, stdout_file=stdout_file, stderr_file=stderr_file) command.start() if get_log_level() == 'DEBUG': logging.log(STDOUT, command.decoded_stdout) logging.log(STDERR, command.decoded_stderr) if capture: return command.decoded_stdout return True except ExternalCommandFailed as e: if allow_fail: logging.log(STDERR, e) sys.exit(e.returncode) else: return None
def __init__(self, type_def, port, logLv = logging.DEBUG): self.type_def = type_def self.port = port self.logLv = logLv self.thread = None self.name = f'test_{self.type_def}_{self.port}' args = " --name {} --tmp -lruntime=debug --ws-port {}".format(self.name, self.port) if type_def != 'europa': args += ' --dev' self.cmd = self.type_def + args self.ec = ExternalCommand(self.cmd)
def execute(cmd, directory=os.getcwd(), capture=False, stdout_file=None, stderr_file=None): """A simple wrapper around executor.""" command = ExternalCommand( cmd, directory=directory, capture=True, capture_stderr=True, stdout_file=stdout_file, stderr_file=stderr_file ) command.start() if get_log_level() == 'DEBUG': logging.log(STDOUT, command.decoded_stdout) logging.log(STDERR, command.decoded_stderr) if capture: return command.decoded_stdout
def check_process_termination(self, method): """Helper method for process termination tests.""" timer = Timer() # We use Executor to launch an external process. with ExternalCommand('sleep', '60', check=False) as cmd: # Verify that proc.unix.UnixProcess.is_running (which is normally # overridden by proc.core.Process.is_running) works as expected, # even though this property isn't actively used in the `proc' # package because we want to deal with not-yet-reclaimed # processes and zombie processes which is very much a Linux # specific thing (hence the override). unix_process = UnixProcess(pid=cmd.pid) assert unix_process.is_running, "UnixProcess.is_running is broken!" # We don't use Executor to control the process, instead we take the # process ID and use it to create a Process object that doesn't # know about Python's subprocess module. linux_process = Process.from_pid(cmd.pid) # We terminate the process using a positive but very low timeout so # that all of the code involved gets a chance to run, but without # significantly slowing down the test suite. getattr(linux_process, method)(timeout=0.1) # Now we can verify our assertions. assert not linux_process.is_running, "Child still running despite graceful termination request!" assert timer.elapsed_time < 10, "It look too long to terminate the child!" # Now comes a hairy bit of Linux implementation details that most # people can thankfully ignore (blissful ignorance :-). Parent # processes are responsible for reclaiming child processes and # until this happens the /proc/[pid] entry remains, which means # the `kill -0' trick used by UnixProcess to detect running # processes doesn't work as expected. Basically this means we # _must_ make sure that waitpid() is called before we can expect # UnixProcess.is_running to behave as expected. cmd.wait() # Now that we've called waitpid() things should work as expected. assert not unix_process.is_running, "UnixProcess.is_running is broken!"
def test_environ(self): """Test that parsing of process environments works as expected.""" unique_value = str(random.random()) with ExternalCommand( 'sleep', '30', environment=dict(unique_value=unique_value)) as sleep_cmd: sleep_proc = Process.from_pid(sleep_cmd.pid) assert sleep_proc.environ['unique_value'] == unique_value
def submit(self, cmd_id, cmd, *args, **kwargs): ec = None if type(cmd) is ExternalCommand or type(cmd) is RemoteCommand: ec = cmd else: ec = ExternalCommand(cmd, *args, **kwargs) ec. async = True self.cmd_records[cmd_id] = ec self.pool.add(ec)
def execute(cmd, directory=os.getcwd(), capture_stdout=False, stdout_file=None, stderr_file=None, max_attempts=1, is_sra=False): """A simple wrapper around executor.""" from executor import ExternalCommand, ExternalCommandFailed attempt = 0 while attempt < max_attempts: attempt += 1 try: command = ExternalCommand(cmd, directory=directory, capture=True, capture_stderr=True, stdout_file=stdout_file, stderr_file=stderr_file) command.start() if get_log_level() == 'DEBUG': logging.log(STDOUT, command.decoded_stdout) logging.log(STDERR, command.decoded_stderr) if capture_stdout: return command.decoded_stdout else: return command.returncode except ExternalCommandFailed as error: logging.error(f'"{cmd}" return exit code {command.returncode}') if is_sra and command.returncode == 3: # The FASTQ isn't on SRA for some reason, try to download from ENA error_msg = command.decoded_stderr.split("\n")[0] logging.error(error_msg) return 'SRA_NOT_FOUND' if attempt < max_attempts: logging.error(f'Retry execution ({attempt} of {max_attempts})') time.sleep(10) else: raise error
def test_notify_desktop(self): """Test that :func:`proc.notify.notify_desktop()` works.""" env = dict((name, 'value') for name in REQUIRED_VARIABLES) with ExternalCommand('sleep 60', environment=env): with MockProgram('notify-send'): notify_desktop( summary="Headless notifications", body= "They actually work! (this message brought to you by the 'proc' test suite :-)", urgency='low', )
def run_cmd(cmdarray, workdir): """Run a command on the shell""" cmd = ExternalCommand(*cmdarray, capture=True, capture_stderr=True, async=True, shell=False, directory=workdir) cmd.start() last_out = '' last_err = '' while cmd.is_running: new_out = cmd.stdout.decode(cmd.encoding, 'ignore').replace(last_out, '') new_err = cmd.stderr.decode(cmd.encoding, 'ignore').replace(last_err, '') last_out += new_out last_err += new_err new_out = new_out.replace(u"\u2018", "'").replace(u"\u2019", "'") new_err = new_err.replace(u"\u2018", "'").replace(u"\u2019", "'") if new_out != '': print(new_out, end='') if new_err != '': print(new_err, end='') if cmd.returncode != 0: raise RuntimeError('Failure to run command') return cmd
def test_is_alive(self): """Test the :func:`proc.core.Process.is_alive` property.""" # Spawn a child that will live for a minute. with ExternalCommand('sleep', '60', check=False) as child: # Construct a process object for the child. process = Process.from_pid(child.pid) # Make sure the process object agrees the child is alive. assert process.is_alive, "Child died before Process.is_alive was called?!" # Kill the child process and give it a moment to terminate # (significantly less time then the process is normally expected to # run, otherwise there's no point in the test below). child.terminate(timeout=10) # Make sure the process object agrees the child is dead. assert not process.is_alive, "Child is still alive even though we killed it?!"
class SubstrateTestEnv: def __init__(self, type_def, port, logLv = logging.DEBUG): self.type_def = type_def self.port = port self.logLv = logLv self.thread = None self.name = f'test_{self.type_def}_{self.port}' args = " --name {} --tmp -lruntime=debug --ws-port {}".format(self.name, self.port) if type_def != 'europa': args += ' --dev' self.cmd = self.type_def + args self.ec = ExternalCommand(self.cmd) @classmethod def create_canvas(cls, port=9944): return cls(type_def='canvas', port=port) @classmethod def create_europa(cls, port=9944): return cls(type_def='europa', port=port) def start_node(self): logging.info("run cmd {}".format(self.cmd)) def loggerThread(): self.ec.start() self.pid = self.ec.pid self.ec.wait() self.thread = threading.Thread(target=loggerThread, name=self.name) self.thread.start() time.sleep(3) # for startup logging.info("start_node {}".format(self.name)) return def stop_node(self): self.ec.kill() return def url(self) -> str: return f'ws://127.0.0.1:{self.port}' def typ(self) -> str: if self.type_def == 'canvas': return 'canvas' if self.type_def == 'europa': return 'default' def types(self) -> dict: if self.type_def == 'canvas': return {'types': {"Address": "AccountId", "LookupSource": "AccountId"}} if self.type_def == 'europa': return {'types': {'LookupSource': 'MultiAddress'}}
def test_suspend_and_resume_signals(self): """Test the sending of ``SIGSTOP``, ``SIGCONT`` and ``SIGTERM`` signals.""" # Spawn a child that will live for a minute. with ExternalCommand('sleep', '60', check=False) as cmd: process = Process.from_pid(cmd.pid) # Suspend the execution of the child process using SIGSTOP. process.suspend() # Test that the child process doesn't respond to SIGTERM once suspended. process.terminate(wait=False) assert process.is_running, "Child responded to signal even though it was suspended?!" # Resume the execution of the child process using SIGCONT. process.resume() # Test that the child process responds to signals again after # having been resumed, but give it a moment to terminate # (significantly less time then the process is normally expected # to run, otherwise there's no point in the test below). process.kill(wait=True, timeout=5) assert not process.is_running, "Child didn't respond to signal even though it was resumed?!"
def submit_command(self, cmd, *args, **kwargs): self.submit(hash(cmd), ExternalCommand(cmd, *args, **kwargs))
def prepare_interactive_shell(self, options): """Refer to :attr:`AbstractContext.prepare_interactive_shell`.""" return ExternalCommand(DEFAULT_SHELL, **self.merge_options(options))
def prepare_command(self, command, options): """Refer to :attr:`AbstractContext.prepare_command`.""" return ExternalCommand(*command, **self.merge_options(options))