Home | History | Annotate | Download | only in common
      1 # Copyright 2013 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """Generic utilities for all python scripts."""
      6 
      7 import atexit
      8 import httplib
      9 import os
     10 import signal
     11 import stat
     12 import subprocess
     13 import sys
     14 import tempfile
     15 import urlparse
     16 
     17 
     18 def GetPlatformName():
     19   """Return a string to be used in paths for the platform."""
     20   if IsWindows():
     21     return 'win'
     22   if IsMac():
     23     return 'mac'
     24   if IsLinux():
     25     return 'linux'
     26   raise NotImplementedError('Unknown platform "%s".' % sys.platform)
     27 
     28 
     29 def IsWindows():
     30   return sys.platform == 'cygwin' or sys.platform.startswith('win')
     31 
     32 
     33 def IsLinux():
     34   return sys.platform.startswith('linux')
     35 
     36 
     37 def IsMac():
     38   return sys.platform.startswith('darwin')
     39 
     40 
     41 def _DeleteDir(path):
     42   """Deletes a directory recursively, which must exist."""
     43   # Don't use shutil.rmtree because it can't delete read-only files on Win.
     44   for root, dirs, files in os.walk(path, topdown=False):
     45     for name in files:
     46       filename = os.path.join(root, name)
     47       os.chmod(filename, stat.S_IWRITE)
     48       os.remove(filename)
     49     for name in dirs:
     50       os.rmdir(os.path.join(root, name))
     51   os.rmdir(path)
     52 
     53 
     54 def Delete(path):
     55   """Deletes the given file or directory (recursively), which must exist."""
     56   if os.path.isdir(path):
     57     _DeleteDir(path)
     58   else:
     59     os.remove(path)
     60 
     61 
     62 def MaybeDelete(path):
     63   """Deletes the given file or directory (recurisvely), if it exists."""
     64   if os.path.exists(path):
     65     Delete(path)
     66 
     67 
     68 def MakeTempDir(parent_dir=None):
     69   """Creates a temporary directory and returns an absolute path to it.
     70 
     71   The temporary directory is automatically deleted when the python interpreter
     72   exits normally.
     73 
     74   Args:
     75     parent_dir: the directory to create the temp dir in. If None, the system
     76                 temp dir is used.
     77 
     78   Returns:
     79     The absolute path to the temporary directory.
     80   """
     81   path = tempfile.mkdtemp(dir=parent_dir)
     82   atexit.register(MaybeDelete, path)
     83   return path
     84 
     85 
     86 def Unzip(zip_path, output_dir):
     87   """Unzips the given zip file using a system installed unzip tool.
     88 
     89   Args:
     90     zip_path: zip file to unzip.
     91     output_dir: directory to unzip the contents of the zip file. The directory
     92                 must exist.
     93 
     94   Raises:
     95     RuntimeError if the unzip operation fails.
     96   """
     97   if IsWindows():
     98     unzip_cmd = ['C:\\Program Files\\7-Zip\\7z.exe', 'x', '-y']
     99   else:
    100     unzip_cmd = ['unzip', '-o']
    101   unzip_cmd += [zip_path]
    102   if RunCommand(unzip_cmd, output_dir) != 0:
    103     raise RuntimeError('Unable to unzip %s to %s' % (zip_path, output_dir))
    104 
    105 
    106 def Kill(pid):
    107   """Terminate the given pid."""
    108   if IsWindows():
    109     subprocess.call(['taskkill.exe', '/T', '/F', '/PID', str(pid)])
    110   else:
    111     os.kill(pid, signal.SIGTERM)
    112 
    113 
    114 def RunCommand(cmd, cwd=None):
    115   """Runs the given command and returns the exit code.
    116 
    117   Args:
    118     cmd: list of command arguments.
    119     cwd: working directory to execute the command, or None if the current
    120          working directory should be used.
    121 
    122   Returns:
    123     The exit code of the command.
    124   """
    125   process = subprocess.Popen(cmd, cwd=cwd)
    126   process.wait()
    127   return process.returncode
    128 
    129 
    130 def DoesUrlExist(url):
    131   """Determines whether a resource exists at the given URL.
    132 
    133   Args:
    134     url: URL to be verified.
    135 
    136   Returns:
    137     True if url exists, otherwise False.
    138   """
    139   parsed = urlparse.urlparse(url)
    140   try:
    141     conn = httplib.HTTPConnection(parsed.netloc)
    142     conn.request('HEAD', parsed.path)
    143     response = conn.getresponse()
    144   except (socket.gaierror, socket.error):
    145     return False
    146   finally:
    147     conn.close()
    148   # Follow both permanent (301) and temporary (302) redirects.
    149   if response.status == 302 or response.status == 301:
    150     return DoesUrlExist(response.getheader('location'))
    151   return response.status == 200
    152