@@ -547,12 +547,30 @@ async def flush(self) -> int:
547547 self .bytes_appended_since_last_flush = 0
548548 return self .persisted_size
549549
550- async def close (self , finalize_on_close = False ) -> Union [int , _storage_v2 .Object ]:
550+ async def close (
551+ self ,
552+ finalize_on_close = False ,
553+ full_object_checksum : Optional [int ] = None ,
554+ ) -> Union [int , _storage_v2 .Object ]:
551555 """Closes the underlying bidi-gRPC stream.
552556
553557 :type finalize_on_close: bool
554558 :param finalize_on_close: Finalizes the Appendable Object. No more data
555559 can be appended.
560+ :type full_object_checksum: int
561+ :param full_object_checksum: (Optional) This should be the CRC32C checksum of
562+ the entire contents of the object as a 32-bit integer.
563+ Used only when finalize_on_close is True.
564+
565+ It can be obtained by running:
566+
567+ .. code-block:: python
568+
569+ import google_crc32c
570+
571+ data = b"Hello, world!"
572+ crc32c_int = google_crc32c.value(data)
573+ print(crc32c_int)
556574
557575 rtype: Union[int, _storage_v2.Object]
558576 returns: Updated `self.persisted_size` by default after closing the
@@ -561,20 +579,32 @@ async def close(self, finalize_on_close=False) -> Union[int, _storage_v2.Object]
561579
562580 :raises ValueError: If the stream is not open (i.e., `open()` has not
563581 been called).
582+ :raises ValueError: If full_object_checksum is provided but
583+ finalize_on_close is False.
584+ :raises google.api_core.exceptions.InvalidArgument: If the provided
585+ full_object_checksum does not match the checksum computed by the
586+ server.
564587
565588 """
566589 if not self ._is_stream_open :
567590 raise ValueError ("Stream is not open. Call open() before close()." )
568591
592+ if full_object_checksum is not None and not finalize_on_close :
593+ raise ValueError (
594+ "full_object_checksum can only be provided when finalize_on_close is True."
595+ )
596+
569597 if finalize_on_close :
570- return await self .finalize ()
598+ return await self .finalize (full_object_checksum = full_object_checksum )
571599
572600 await self .write_obj_stream .close ()
573601
574602 self ._is_stream_open = False
575603 return self .persisted_size
576604
577- async def finalize (self ) -> _storage_v2 .Object :
605+ async def finalize (
606+ self , full_object_checksum : Optional [int ] = None
607+ ) -> _storage_v2 .Object :
578608 """Finalizes the Appendable Object.
579609
580610 Note: Once finalized no more data can be appended.
@@ -585,18 +615,40 @@ async def finalize(self) -> _storage_v2.Object:
585615 However if `.finalize()` is called no more data can be appended to the
586616 object.
587617
618+ :type full_object_checksum: int
619+ :param full_object_checksum: (Optional) This should be the CRC32C checksum of
620+ the entire contents of the object as a 32-bit integer.
621+
622+ It can be obtained by running:
623+
624+ .. code-block:: python
625+
626+ import google_crc32c
627+
628+ data = b"Hello, world!"
629+ crc32c_int = google_crc32c.value(data)
630+ print(crc32c_int)
631+
588632 rtype: google.cloud.storage_v2.types.Object
589633 returns: The finalized object resource.
590634
591635 :raises ValueError: If the stream is not open (i.e., `open()` has not
592636 been called).
637+ :raises google.api_core.exceptions.InvalidArgument: If the provided
638+ full_object_checksum does not match the checksum computed by the
639+ server.
593640 """
594641 if not self ._is_stream_open :
595642 raise ValueError ("Stream is not open. Call open() before finalize()." )
596643
597- await self .write_obj_stream .send (
598- _storage_v2 .BidiWriteObjectRequest (finish_write = True )
599- )
644+ finalize_req = _storage_v2 .BidiWriteObjectRequest (finish_write = True )
645+
646+ if full_object_checksum is not None :
647+ finalize_req .object_checksums = _storage_v2 .ObjectChecksums (
648+ crc32c = full_object_checksum
649+ )
650+
651+ await self .write_obj_stream .send (finalize_req )
600652 response = await self .write_obj_stream .recv ()
601653 self .object_resource = response .resource
602654 self .persisted_size = self .object_resource .size
0 commit comments