| # Copyright 2013 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. |
| |
| """Generic utilities for all python scripts.""" |
| |
| import atexit |
| import httplib |
| import os |
| import signal |
| import stat |
| import subprocess |
| import sys |
| import tempfile |
| import urlparse |
| |
| |
| def GetPlatformName(): |
| """Return a string to be used in paths for the platform.""" |
| if IsWindows(): |
| return 'win' |
| if IsMac(): |
| return 'mac' |
| if IsLinux(): |
| return 'linux' |
| raise NotImplementedError('Unknown platform "%s".' % sys.platform) |
| |
| |
| def IsWindows(): |
| return sys.platform == 'cygwin' or sys.platform.startswith('win') |
| |
| |
| def IsLinux(): |
| return sys.platform.startswith('linux') |
| |
| |
| def IsMac(): |
| return sys.platform.startswith('darwin') |
| |
| |
| def _DeleteDir(path): |
| """Deletes a directory recursively, which must exist.""" |
| # Don't use shutil.rmtree because it can't delete read-only files on Win. |
| for root, dirs, files in os.walk(path, topdown=False): |
| for name in files: |
| filename = os.path.join(root, name) |
| os.chmod(filename, stat.S_IWRITE) |
| os.remove(filename) |
| for name in dirs: |
| os.rmdir(os.path.join(root, name)) |
| os.rmdir(path) |
| |
| |
| def Delete(path): |
| """Deletes the given file or directory (recursively), which must exist.""" |
| if os.path.isdir(path): |
| _DeleteDir(path) |
| else: |
| os.remove(path) |
| |
| |
| def MaybeDelete(path): |
| """Deletes the given file or directory (recurisvely), if it exists.""" |
| if os.path.exists(path): |
| Delete(path) |
| |
| |
| def MakeTempDir(parent_dir=None): |
| """Creates a temporary directory and returns an absolute path to it. |
| |
| The temporary directory is automatically deleted when the python interpreter |
| exits normally. |
| |
| Args: |
| parent_dir: the directory to create the temp dir in. If None, the system |
| temp dir is used. |
| |
| Returns: |
| The absolute path to the temporary directory. |
| """ |
| path = tempfile.mkdtemp(dir=parent_dir) |
| atexit.register(MaybeDelete, path) |
| return path |
| |
| |
| def Unzip(zip_path, output_dir): |
| """Unzips the given zip file using a system installed unzip tool. |
| |
| Args: |
| zip_path: zip file to unzip. |
| output_dir: directory to unzip the contents of the zip file. The directory |
| must exist. |
| |
| Raises: |
| RuntimeError if the unzip operation fails. |
| """ |
| if IsWindows(): |
| unzip_cmd = ['C:\\Program Files\\7-Zip\\7z.exe', 'x', '-y'] |
| else: |
| unzip_cmd = ['unzip', '-o'] |
| unzip_cmd += [zip_path] |
| if RunCommand(unzip_cmd, output_dir) != 0: |
| raise RuntimeError('Unable to unzip %s to %s' % (zip_path, output_dir)) |
| |
| |
| def Kill(pid): |
| """Terminate the given pid.""" |
| if IsWindows(): |
| subprocess.call(['taskkill.exe', '/T', '/F', '/PID', str(pid)]) |
| else: |
| os.kill(pid, signal.SIGTERM) |
| |
| |
| def RunCommand(cmd, cwd=None): |
| """Runs the given command and returns the exit code. |
| |
| Args: |
| cmd: list of command arguments. |
| cwd: working directory to execute the command, or None if the current |
| working directory should be used. |
| |
| Returns: |
| The exit code of the command. |
| """ |
| process = subprocess.Popen(cmd, cwd=cwd) |
| process.wait() |
| return process.returncode |
| |
| |
| def DoesUrlExist(url): |
| """Determines whether a resource exists at the given URL. |
| |
| Args: |
| url: URL to be verified. |
| |
| Returns: |
| True if url exists, otherwise False. |
| """ |
| parsed = urlparse.urlparse(url) |
| try: |
| conn = httplib.HTTPConnection(parsed.netloc) |
| conn.request('HEAD', parsed.path) |
| response = conn.getresponse() |
| except (socket.gaierror, socket.error): |
| return False |
| finally: |
| conn.close() |
| # Follow both permanent (301) and temporary (302) redirects. |
| if response.status == 302 or response.status == 301: |
| return DoesUrlExist(response.getheader('location')) |
| return response.status == 200 |