parameters: (url, context, force, dontExtract = None)
docstring: Download and extract the archive file at given URL to the
      source directory specified in the context.
  
      dontExtract may be a sequence of path prefixes that will
      be excluded when extracting the archive.
  
      Returns the absolute path to the directory where files have
      been extracted.
docstring_summary: Download and extract the archive file at given URL to the
      source directory specified in the context.
docstring_tokens: Download and extract the archive file at given URL to the source directory specified in the context .
function: def DownloadURL(url, context, force, dontExtract = None):
      """Download and extract the archive file at given URL to the
      source directory specified in the context.
  
      dontExtract may be a sequence of path prefixes that will
      be excluded when extracting the archive.
  
      Returns the absolute path to the directory where files have
      been extracted."""
      with CurrentWorkingDirectory(context.srcDir):
          # Extract filename from URL and see if file already exists.
          filename = url.split("/")[-1]
          if force and os.path.exists(filename):
              os.remove(filename)
  
          if os.path.exists(filename):
              PrintInfo("{0} already exists, skipping download"
                        .format(os.path.abspath(filename)))
          else:
              PrintInfo("Downloading {0} to {1}"
                        .format(url, os.path.abspath(filename)))
  
              # To work around occasional hiccups with downloading from websites
              # (SSL validation errors, etc.), retry a few times if we don't
              # succeed in downloading the file.
              maxRetries = 5
              lastError = None
  
              # Download to a temporary file and rename it to the expected
              # filename when complete. This ensures that incomplete downloads
              # will be retried if the script is run again.
              tmpFilename = filename + ".tmp"
              if os.path.exists(tmpFilename):
                  os.remove(tmpFilename)
  
              for i in range(maxRetries):
                  try:
                      context.downloader(url, tmpFilename)
                      break
                  except Exception as e:
                      PrintCommandOutput("Retrying download due to error: {err}\n"
                                         .format(err=e))
                      lastError = e
              else:
                  errorMsg = str(lastError)
                  if "SSL: TLSV1_ALERT_PROTOCOL_VERSION" in errorMsg:
                      errorMsg += ("\n\n"
                                   "Your OS or version of Python may not support "
                                   "TLS v1.2+, which is required for downloading "
                                   "files from certain websites. This support "
                                   "was added in Python 2.7.9."
                                   "\n\n"
                                   "You can use curl to download dependencies "
                                   "by installing it in your PATH and re-running "
                                   "this script.")
                  raise RuntimeError("Failed to download {url}: {err}"
                                     .format(url=url, err=errorMsg))
  
              shutil.move(tmpFilename, filename)
  
          # Open the archive and retrieve the name of the top-most directory.
          # This assumes the archive contains a single directory with all
          # of the contents beneath it.
          archive = None
          rootDir = None
          members = None
          try:
              if tarfile.is_tarfile(filename):
                  archive = tarfile.open(filename)
                  rootDir = archive.getnames()[0].split('/')[0]
                  if dontExtract != None:
                      members = (m for m in archive.getmembers()
                                 if not any((fnmatch.fnmatch(m.name, p)
                                             for p in dontExtract)))
              elif zipfile.is_zipfile(filename):
                  archive = zipfile.ZipFile(filename)
                  rootDir = archive.namelist()[0].split('/')[0]
                  if dontExtract != None:
                      members = (m for m in archive.getnames()
                                 if not any((fnmatch.fnmatch(m, p)
                                             for p in dontExtract)))
              else:
                  raise RuntimeError("unrecognized archive file type")
  
              with archive:
                  extractedPath = os.path.abspath(rootDir)
                  if force and os.path.isdir(extractedPath):
                      shutil.rmtree(extractedPath)
  
                  if os.path.isdir(extractedPath):
                      PrintInfo("Directory {0} already exists, skipping extract"
                                .format(extractedPath))
                  else:
                      PrintInfo("Extracting archive to {0}".format(extractedPath))
  
                      # Extract to a temporary directory then move the contents
                      # to the expected location when complete. This ensures that
                      # incomplete extracts will be retried if the script is run
                      # again.
                      tmpExtractedPath = os.path.abspath("extract_dir")
                      if os.path.isdir(tmpExtractedPath):
                          shutil.rmtree(tmpExtractedPath)
  
                      archive.extractall(tmpExtractedPath, members=members)
  
                      shutil.move(os.path.join(tmpExtractedPath, rootDir),
                                  extractedPath)
                      shutil.rmtree(tmpExtractedPath)
  
                  return extractedPath
          except Exception as e:
              # If extraction failed for whatever reason, assume the
              # archive file was bad and move it aside so that re-running
              # the script will try downloading and extracting again.
              shutil.move(filename, filename + ".bad")
              raise RuntimeError("Failed to extract archive {filename}: {err}"
                                 .format(filename=filename, err=e))
function_tokens: def DownloadURL ( url , context , force , dontExtract = None ) : with CurrentWorkingDirectory ( context . srcDir ) : # Extract filename from URL and see if file already exists. filename = url . split ( "/" ) [ - 1 ] if force and os . path . exists ( filename ) : os . remove ( filename ) if os . path . exists ( filename ) : PrintInfo ( "{0} already exists, skipping download" . format ( os . path . abspath ( filename ) ) ) else : PrintInfo ( "Downloading {0} to {1}" . format ( url , os . path . abspath ( filename ) ) ) # To work around occasional hiccups with downloading from websites # (SSL validation errors, etc.), retry a few times if we don't # succeed in downloading the file. maxRetries = 5 lastError = None # Download to a temporary file and rename it to the expected # filename when complete. This ensures that incomplete downloads # will be retried if the script is run again. tmpFilename = filename + ".tmp" if os . path . exists ( tmpFilename ) : os . remove ( tmpFilename ) for i in range ( maxRetries ) : try : context . downloader ( url , tmpFilename ) break except Exception as e : PrintCommandOutput ( "Retrying download due to error: {err}\n" . format ( err = e ) ) lastError = e else : errorMsg = str ( lastError ) if "SSL: TLSV1_ALERT_PROTOCOL_VERSION" in errorMsg : errorMsg += ( "\n\n" "Your OS or version of Python may not support " "TLS v1.2+, which is required for downloading " "files from certain websites. This support " "was added in Python 2.7.9." "\n\n" "You can use curl to download dependencies " "by installing it in your PATH and re-running " "this script." ) raise RuntimeError ( "Failed to download {url}: {err}" . format ( url = url , err = errorMsg ) ) shutil . move ( tmpFilename , filename ) # Open the archive and retrieve the name of the top-most directory. # This assumes the archive contains a single directory with all # of the contents beneath it. archive = None rootDir = None members = None try : if tarfile . is_tarfile ( filename ) : archive = tarfile . open ( filename ) rootDir = archive . getnames ( ) [ 0 ] . split ( '/' ) [ 0 ] if dontExtract != None : members = ( m for m in archive . getmembers ( ) if not any ( ( fnmatch . fnmatch ( m . name , p ) for p in dontExtract ) ) ) elif zipfile . is_zipfile ( filename ) : archive = zipfile . ZipFile ( filename ) rootDir = archive . namelist ( ) [ 0 ] . split ( '/' ) [ 0 ] if dontExtract != None : members = ( m for m in archive . getnames ( ) if not any ( ( fnmatch . fnmatch ( m , p ) for p in dontExtract ) ) ) else : raise RuntimeError ( "unrecognized archive file type" ) with archive : extractedPath = os . path . abspath ( rootDir ) if force and os . path . isdir ( extractedPath ) : shutil . rmtree ( extractedPath ) if os . path . isdir ( extractedPath ) : PrintInfo ( "Directory {0} already exists, skipping extract" . format ( extractedPath ) ) else : PrintInfo ( "Extracting archive to {0}" . format ( extractedPath ) ) # Extract to a temporary directory then move the contents # to the expected location when complete. This ensures that # incomplete extracts will be retried if the script is run # again. tmpExtractedPath = os . path . abspath ( "extract_dir" ) if os . path . isdir ( tmpExtractedPath ) : shutil . rmtree ( tmpExtractedPath ) archive . extractall ( tmpExtractedPath , members = members ) shutil . move ( os . path . join ( tmpExtractedPath , rootDir ) , extractedPath ) shutil . rmtree ( tmpExtractedPath ) return extractedPath except Exception as e : # If extraction failed for whatever reason, assume the # archive file was bad and move it aside so that re-running # the script will try downloading and extracting again. shutil . move ( filename , filename + ".bad" ) raise RuntimeError ( "Failed to extract archive {filename}: {err}" . format ( filename = filename , err = e ) )