class_docstr: Represent a GCS Object, including all its revisions.
class_docstr_tok: ["Represent","a","GCS","Object",",","including","all","its","revisions","."]
docstr: Execute an iteration of `Objects: rewrite.
  
  Objects: rewrite may need to be called multiple times before it
  succeeds. Only objects in the same location, with the same encryption,
  are guaranteed to complete in a single request.
  
  The implementation simulates some, but not all, the behaviors of the
  server, in particular, only rewrites within the same bucket and smaller
  than 1MiB complete immediately.
  
  :param gcs_url:str the root URL for the fake GCS service.
  :param request:flask.Request the contents of the HTTP request.
  :param destination_bucket:str where will the object be placed after the
      rewrite operation completes.
  :param destination_object:str the name of the object when the rewrite
      operation completes.
  :return: a dictionary prepared for JSON encoding of a
      `Objects: rewrite` response.
  :rtype:dict
docstr_tok: ["Execute","an","iteration","of","`","Objects",":","rewrite",".","Objects",":","rewrite","may","need","to","be","called","multiple","times","before","it","succeeds",".","Only","objects","in","the","same","location",",","with","the","same","encryption",",","are","guaranteed","to","complete","in","a","single","request",".","The","implementation","simulates","some",",","but","not","all",",","the","behaviors","of","the","server",",","in","particular",",","only","rewrites","within","the","same","bucket","and","smaller","than","1MiB","complete","immediately",".",":","param","gcs_url",":","str","the","root","URL","for","the","fake","GCS","service",".",":","param","request",":","flask.Request","the","contents","of","the","HTTP","request",".",":","param","destination_bucket",":","str","where","will","the","object","be","placed","after","the","rewrite","operation","completes",".",":","param","destination_object",":","str","the","name","of","the","object","when","the","rewrite","operation","completes",".",":","return",":","a","dictionary","prepared","for","JSON","encoding","of","a","`","Objects",":","rewrite","`","response",".",":","rtype",":","dict"]
code: def rewrite_step(
      self, gcs_url, request, destination_bucket, destination_object
  ):
      """Execute an iteration of `Objects: rewrite.
  
      Objects: rewrite may need to be called multiple times before it
      succeeds. Only objects in the same location, with the same encryption,
      are guaranteed to complete in a single request.
  
      The implementation simulates some, but not all, the behaviors of the
      server, in particular, only rewrites within the same bucket and smaller
      than 1MiB complete immediately.
  
      :param gcs_url:str the root URL for the fake GCS service.
      :param request:flask.Request the contents of the HTTP request.
      :param destination_bucket:str where will the object be placed after the
          rewrite operation completes.
      :param destination_object:str the name of the object when the rewrite
          operation completes.
      :return: a dictionary prepared for JSON encoding of a
          `Objects: rewrite` response.
      :rtype:dict
      """
      body = json.loads(request.data)
      rewrite_token = request.args.get("rewriteToken")
      if rewrite_token is not None and rewrite_token != "":
          # Note that we remove the rewrite operation, not just look it up.
          # That way if the operation completes in this call, and/or fails,
          # it is already removed. We need to insert it with a new token
          # anyway, so this makes sense.
          rewrite = self.rewrite_operations.pop(rewrite_token, None)
          if rewrite is None:
              raise error_response.ErrorResponse(
                  "Invalid or expired token in rewrite", status_code=410
              )
      else:
          rewrite_token, rewrite = self.make_rewrite_operation(
              request, destination_bucket, destination_bucket
          )
  
      # Compare the difference to the original arguments, on the first call
      # this is a waste, but the code is easier to follow.
      current_arguments = self.capture_rewrite_operation_arguments(
          request, destination_bucket, destination_object
      )
      diff = set(current_arguments) ^ set(
          rewrite.get("original_arguments")
      )
      if len(diff) != 0:
          raise error_response.ErrorResponse(
              "Mismatched arguments to rewrite", status_code=412
          )
  
      # This will raise if the version is deleted while the operation is in
      # progress.
      source = self.get_revision_by_generation(
          rewrite.get("actual_generation")
      )
      source.validate_encryption_for_read(
          request, prefix="x-goog-copy-source-encryption"
      )
      bytes_rewritten = rewrite.get("bytes_rewritten")
      bytes_rewritten += 1024 * 1024
      result = {
          "kind": "storage#rewriteResponse",
          "objectSize": len(source.media),
      }
      if bytes_rewritten >= len(source.media):
          bytes_rewritten = len(source.media)
          rewrite["bytes_rewritten"] = bytes_rewritten
          # Success, the operation completed. Return the new object:
          object_path, destination = testbench_utils.get_object(
              destination_bucket,
              destination_object,
              GcsObject(destination_bucket, destination_object),
          )
          revision = destination.rewrite_finish(
              gcs_url, request, body, source
          )
          testbench_utils.insert_object(object_path, destination)
          result["done"] = True
          result["resource"] = revision.metadata
          rewrite_token = ""
      else:
          rewrite["bytes_rewritten"] = bytes_rewritten
          rewrite_token = GcsObject.make_rewrite_token(
              rewrite,
              destination_bucket,
              destination_object,
              source.generation,
          )
          self.rewrite_operations[rewrite_token] = rewrite
          result["done"] = False
  
      result.update(
          {
              "totalBytesRewritten": bytes_rewritten,
              "rewriteToken": rewrite_token,
          }
      )
      return result
  
imports: import base64
  import crc32c
  import error_response
  import hashlib
  import json
  import struct
  import testbench_utils
  import time
label_desc: Use image node_id 21 for calling the GcsObject obj's underlying member method code with example usage: obj.rewrite_step(gcs_url, request, destination_bucket, destination_object) and returns: result