@log_calls
  def upload(self, local_path, store_path, clobber=False, show_info=False):
    self._log_upload(local_path, store_path, show_info=show_info)

    remote_path = join_path(self.root_dir, store_path)
    if not clobber and self.exists(remote_path):
      raise FileExists("upload aborted: file exists: %s" % store_path)

    fsize = os.path.getsize(local_path)
    local_md5 = file_md5(local_path)
    if S3_SINGLEPART_MAX_SIZE < fsize:
      # Don't use multipart upload unless we need to (simpler, and also we might have an older version of boto)
      k = boto.s3.key.Key(self.root_bucket)
      k.key = remote_path
      k.set_metadata(ZINC_S3_MD5_NAME, local_md5)
      k.set_contents_from_filename(local_path)
    else:
      if not hasattr(self.root_bucket, "initiate_multipart_upload"):
        raise Failure("S3 multipart upload not supported for file of size %s (%s) -- boto library is not current?" % (fsize, local_path))
      mpu = self.root_bucket.initiate_multipart_upload(remote_path, metadata = {ZINC_S3_MD5_NAME: local_md5})
      part = 1
      bytes_done = 0
      try:
        with open(local_path, 'rb') as f:
          # For now this is single threaded; concurrency could speed it up, depending on disk/network performance.
          while bytes_done < fsize:
            log.debug("uploading part %s of %s -> %s", part, local_path, remote_path)
            mpu.upload_part_from_file(cStringIO.StringIO(f.read(S3_MULTIPART_CHUNK_SIZE)), part)
            bytes_done += S3_MULTIPART_CHUNK_SIZE
            part += 1
        cmpu = mpu.complete_upload()
        log.debug("uploading complete %s -> %s: %s (etag %s)", local_path, remote_path, cmpu, cmpu.etag)
      except Exception, e:
        mpu.cancel_upload()
        raise Failure("error uploading '%s' to S3 location '%s': %s" % (local_path, remote_path, e))
dataset/ETHPy150Open bloomreach/zinc/zinc.py/S3Store.upload/swapped operands of `<`