def DoUpload(self, paths, openfunc):
    """Uploads a new appversion with the given config and files to the server.

    Args:
      paths: An iterator that yields the relative paths of the files to upload.
      openfunc: A function that takes a path and returns a file-like object.

    Returns:
      An appinfo.AppInfoSummary if one was returned from the server, None
      otherwise.
    """
    logging.info('Reading app configuration.')

    StatusUpdate('\nStarting update of %s' % self.Describe())


    path = ''
    try:
      self.resource_limits = GetResourceLimits(self.rpcserver, self.config)

      StatusUpdate('Scanning files on local disk.')
      num_files = 0
      for path in paths:
        file_handle = openfunc(path)
        file_classification = FileClassification(self.config, path)
        try:
          file_length = GetFileLength(file_handle)
          if file_classification.IsApplicationFile():
            max_size = self.resource_limits['max_file_size']
          else:
            max_size = self.resource_limits['max_blob_size']
          if file_length > max_size:
            logging.error('Ignoring file \'%s\': Too long '
                          '(max %d bytes, file is %d bytes)',
                          path, max_size, file_length)
          else:
            logging.info('Processing file \'%s\'', path)
            self.AddFile(path, file_handle)
        finally:
          file_handle.close()
        num_files += 1
        if num_files % 500 == 0:
          StatusUpdate('Scanned %d files.' % num_files)
    except KeyboardInterrupt:
      logging.info('User interrupted. Aborting.')
      raise
    except EnvironmentError, e:
      logging.error('An error occurred processing file \'%s\': %s. Aborting.',
                    path, e)
      raise

    app_summary = None
    try:

      missing_files = self.Begin()
      if missing_files:
        StatusUpdate('Uploading %d files and blobs.' % len(missing_files))
        num_files = 0
        for missing_file in missing_files:
          file_handle = openfunc(missing_file)
          try:
            self.UploadFile(missing_file, file_handle)
          finally:
            file_handle.close()
          num_files += 1
          if num_files % 500 == 0:
            StatusUpdate('Processed %d out of %s.' %
                         (num_files, len(missing_files)))

        self.file_batcher.Flush()
        self.blob_batcher.Flush()
        self.errorblob_batcher.Flush()
        StatusUpdate('Uploaded %d files and blobs' % num_files)


      if (self.config.derived_file_type and
          appinfo.PYTHON_PRECOMPILED in self.config.derived_file_type):
        try:
          self.Precompile()
        except urllib2.HTTPError, e:

          ErrorUpdate('Error %d: --- begin server output ---\n'
                      '%s\n--- end server output ---' %
                      (e.code, e.read().rstrip('\n')))
          if e.code == 422 or self.config.runtime == 'go':






            raise
          print >>self.error_fh, (
              'Precompilation failed. Your app can still serve but may '
              'have reduced startup performance. You can retry the update '
              'later to retry the precompilation step.')


      app_summary = self.Commit()
      StatusUpdate('Completed update of %s' % self.Describe())

    except __HOLE__:

      logging.info('User interrupted. Aborting.')
      self.Rollback()
      raise
    except urllib2.HTTPError, err:

      logging.info('HTTP Error (%s)', err)
      self.Rollback()
      raise
    except:
      logging.exception('An unexpected error occurred. Aborting.')
      self.Rollback()
      raise

    logging.info('Done!')
    return app_summary
dataset/ETHPy150Open AppScale/appscale/AppServer/google/appengine/tools/appcfg.py/AppVersionUpload.DoUpload