Index: build/android/devil/utils/cmd_helper.py |
diff --git a/build/android/devil/utils/cmd_helper.py b/build/android/devil/utils/cmd_helper.py |
deleted file mode 100644 |
index 57e8987558d4a3209c1be35d6f905ed3485cecc4..0000000000000000000000000000000000000000 |
--- a/build/android/devil/utils/cmd_helper.py |
+++ /dev/null |
@@ -1,311 +0,0 @@ |
-# Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-# Use of this source code is governed by a BSD-style license that can be |
-# found in the LICENSE file. |
- |
-"""A wrapper for subprocess to make calling shell commands easier.""" |
- |
-import logging |
-import os |
-import pipes |
-import select |
-import signal |
-import string |
-import StringIO |
-import subprocess |
-import time |
- |
-# fcntl is not available on Windows. |
-try: |
- import fcntl |
-except ImportError: |
- fcntl = None |
- |
-_SafeShellChars = frozenset(string.ascii_letters + string.digits + '@%_-+=:,./') |
- |
-def SingleQuote(s): |
- """Return an shell-escaped version of the string using single quotes. |
- |
- Reliably quote a string which may contain unsafe characters (e.g. space, |
- quote, or other special characters such as '$'). |
- |
- The returned value can be used in a shell command line as one token that gets |
- to be interpreted literally. |
- |
- Args: |
- s: The string to quote. |
- |
- Return: |
- The string quoted using single quotes. |
- """ |
- return pipes.quote(s) |
- |
-def DoubleQuote(s): |
- """Return an shell-escaped version of the string using double quotes. |
- |
- Reliably quote a string which may contain unsafe characters (e.g. space |
- or quote characters), while retaining some shell features such as variable |
- interpolation. |
- |
- The returned value can be used in a shell command line as one token that gets |
- to be further interpreted by the shell. |
- |
- The set of characters that retain their special meaning may depend on the |
- shell implementation. This set usually includes: '$', '`', '\', '!', '*', |
- and '@'. |
- |
- Args: |
- s: The string to quote. |
- |
- Return: |
- The string quoted using double quotes. |
- """ |
- if not s: |
- return '""' |
- elif all(c in _SafeShellChars for c in s): |
- return s |
- else: |
- return '"' + s.replace('"', '\\"') + '"' |
- |
- |
-def ShrinkToSnippet(cmd_parts, var_name, var_value): |
- """Constructs a shell snippet for a command using a variable to shrink it. |
- |
- Takes into account all quoting that needs to happen. |
- |
- Args: |
- cmd_parts: A list of command arguments. |
- var_name: The variable that holds var_value. |
- var_value: The string to replace in cmd_parts with $var_name |
- |
- Returns: |
- A shell snippet that does not include setting the variable. |
- """ |
- def shrink(value): |
- parts = (x and SingleQuote(x) for x in value.split(var_value)) |
- with_substitutions = ('"$%s"' % var_name).join(parts) |
- return with_substitutions or "''" |
- |
- return ' '.join(shrink(part) for part in cmd_parts) |
- |
- |
-def Popen(args, stdout=None, stderr=None, shell=None, cwd=None, env=None): |
- return subprocess.Popen( |
- args=args, cwd=cwd, stdout=stdout, stderr=stderr, |
- shell=shell, close_fds=True, env=env, |
- preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL)) |
- |
- |
-def Call(args, stdout=None, stderr=None, shell=None, cwd=None, env=None): |
- pipe = Popen(args, stdout=stdout, stderr=stderr, shell=shell, cwd=cwd, |
- env=env) |
- pipe.communicate() |
- return pipe.wait() |
- |
- |
-def RunCmd(args, cwd=None): |
- """Opens a subprocess to execute a program and returns its return value. |
- |
- Args: |
- args: A string or a sequence of program arguments. The program to execute is |
- the string or the first item in the args sequence. |
- cwd: If not None, the subprocess's current directory will be changed to |
- |cwd| before it's executed. |
- |
- Returns: |
- Return code from the command execution. |
- """ |
- logging.info(str(args) + ' ' + (cwd or '')) |
- return Call(args, cwd=cwd) |
- |
- |
-def GetCmdOutput(args, cwd=None, shell=False): |
- """Open a subprocess to execute a program and returns its output. |
- |
- Args: |
- args: A string or a sequence of program arguments. The program to execute is |
- the string or the first item in the args sequence. |
- cwd: If not None, the subprocess's current directory will be changed to |
- |cwd| before it's executed. |
- shell: Whether to execute args as a shell command. |
- |
- Returns: |
- Captures and returns the command's stdout. |
- Prints the command's stderr to logger (which defaults to stdout). |
- """ |
- (_, output) = GetCmdStatusAndOutput(args, cwd, shell) |
- return output |
- |
- |
-def _ValidateAndLogCommand(args, cwd, shell): |
- if isinstance(args, basestring): |
- if not shell: |
- raise Exception('string args must be run with shell=True') |
- else: |
- if shell: |
- raise Exception('array args must be run with shell=False') |
- args = ' '.join(SingleQuote(c) for c in args) |
- if cwd is None: |
- cwd = '' |
- else: |
- cwd = ':' + cwd |
- logging.info('[host]%s> %s', cwd, args) |
- return args |
- |
- |
-def GetCmdStatusAndOutput(args, cwd=None, shell=False): |
- """Executes a subprocess and returns its exit code and output. |
- |
- Args: |
- args: A string or a sequence of program arguments. The program to execute is |
- the string or the first item in the args sequence. |
- cwd: If not None, the subprocess's current directory will be changed to |
- |cwd| before it's executed. |
- shell: Whether to execute args as a shell command. Must be True if args |
- is a string and False if args is a sequence. |
- |
- Returns: |
- The 2-tuple (exit code, output). |
- """ |
- status, stdout, stderr = GetCmdStatusOutputAndError( |
- args, cwd=cwd, shell=shell) |
- |
- if stderr: |
- logging.critical(stderr) |
- if len(stdout) > 4096: |
- logging.debug('Truncated output:') |
- logging.debug(stdout[:4096]) |
- return (status, stdout) |
- |
-def GetCmdStatusOutputAndError(args, cwd=None, shell=False): |
- """Executes a subprocess and returns its exit code, output, and errors. |
- |
- Args: |
- args: A string or a sequence of program arguments. The program to execute is |
- the string or the first item in the args sequence. |
- cwd: If not None, the subprocess's current directory will be changed to |
- |cwd| before it's executed. |
- shell: Whether to execute args as a shell command. Must be True if args |
- is a string and False if args is a sequence. |
- |
- Returns: |
- The 2-tuple (exit code, output). |
- """ |
- _ValidateAndLogCommand(args, cwd, shell) |
- pipe = Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, |
- shell=shell, cwd=cwd) |
- stdout, stderr = pipe.communicate() |
- return (pipe.returncode, stdout, stderr) |
- |
- |
-class TimeoutError(Exception): |
- """Module-specific timeout exception.""" |
- |
- def __init__(self, output=None): |
- super(TimeoutError, self).__init__() |
- self._output = output |
- |
- @property |
- def output(self): |
- return self._output |
- |
- |
-def _IterProcessStdout(process, timeout=None, buffer_size=4096, |
- poll_interval=1): |
- assert fcntl, 'fcntl module is required' |
- try: |
- # Enable non-blocking reads from the child's stdout. |
- child_fd = process.stdout.fileno() |
- fl = fcntl.fcntl(child_fd, fcntl.F_GETFL) |
- fcntl.fcntl(child_fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) |
- |
- end_time = (time.time() + timeout) if timeout else None |
- while True: |
- if end_time and time.time() > end_time: |
- raise TimeoutError() |
- read_fds, _, _ = select.select([child_fd], [], [], poll_interval) |
- if child_fd in read_fds: |
- data = os.read(child_fd, buffer_size) |
- if not data: |
- break |
- yield data |
- if process.poll() is not None: |
- break |
- finally: |
- try: |
- # Make sure the process doesn't stick around if we fail with an |
- # exception. |
- process.kill() |
- except OSError: |
- pass |
- process.wait() |
- |
- |
-def GetCmdStatusAndOutputWithTimeout(args, timeout, cwd=None, shell=False, |
- logfile=None): |
- """Executes a subprocess with a timeout. |
- |
- Args: |
- args: List of arguments to the program, the program to execute is the first |
- element. |
- timeout: the timeout in seconds or None to wait forever. |
- cwd: If not None, the subprocess's current directory will be changed to |
- |cwd| before it's executed. |
- shell: Whether to execute args as a shell command. Must be True if args |
- is a string and False if args is a sequence. |
- logfile: Optional file-like object that will receive output from the |
- command as it is running. |
- |
- Returns: |
- The 2-tuple (exit code, output). |
- """ |
- _ValidateAndLogCommand(args, cwd, shell) |
- output = StringIO.StringIO() |
- process = Popen(args, cwd=cwd, shell=shell, stdout=subprocess.PIPE, |
- stderr=subprocess.STDOUT) |
- try: |
- for data in _IterProcessStdout(process, timeout=timeout): |
- if logfile: |
- logfile.write(data) |
- output.write(data) |
- except TimeoutError: |
- raise TimeoutError(output.getvalue()) |
- |
- return process.returncode, output.getvalue() |
- |
- |
-def IterCmdOutputLines(args, timeout=None, cwd=None, shell=False, |
- check_status=True): |
- """Executes a subprocess and continuously yields lines from its output. |
- |
- Args: |
- args: List of arguments to the program, the program to execute is the first |
- element. |
- cwd: If not None, the subprocess's current directory will be changed to |
- |cwd| before it's executed. |
- shell: Whether to execute args as a shell command. Must be True if args |
- is a string and False if args is a sequence. |
- check_status: A boolean indicating whether to check the exit status of the |
- process after all output has been read. |
- |
- Yields: |
- The output of the subprocess, line by line. |
- |
- Raises: |
- CalledProcessError if check_status is True and the process exited with a |
- non-zero exit status. |
- """ |
- cmd = _ValidateAndLogCommand(args, cwd, shell) |
- process = Popen(args, cwd=cwd, shell=shell, stdout=subprocess.PIPE, |
- stderr=subprocess.STDOUT) |
- buffer_output = '' |
- for data in _IterProcessStdout(process, timeout=timeout): |
- buffer_output += data |
- has_incomplete_line = buffer_output[-1] not in '\r\n' |
- lines = buffer_output.splitlines() |
- buffer_output = lines.pop() if has_incomplete_line else '' |
- for line in lines: |
- yield line |
- if buffer_output: |
- yield buffer_output |
- if check_status and process.returncode: |
- raise subprocess.CalledProcessError(process.returncode, cmd) |