@@ -197,7 +197,6 @@ def copy(
197197 destination_object = destination_object or source_object
198198
199199 if source_bucket == destination_bucket and source_object == destination_object :
200-
201200 raise ValueError (
202201 f"Either source/destination bucket or source/destination object must be different, "
203202 f"not both the same: bucket={ source_bucket } , object={ source_object } "
@@ -282,6 +281,7 @@ def download(
282281 chunk_size : int | None = None ,
283282 timeout : int | None = DEFAULT_TIMEOUT ,
284283 num_max_attempts : int | None = 1 ,
284+ user_project : str | None = None ,
285285 ) -> bytes :
286286 ...
287287
@@ -294,6 +294,7 @@ def download(
294294 chunk_size : int | None = None ,
295295 timeout : int | None = DEFAULT_TIMEOUT ,
296296 num_max_attempts : int | None = 1 ,
297+ user_project : str | None = None ,
297298 ) -> str :
298299 ...
299300
@@ -305,6 +306,7 @@ def download(
305306 chunk_size : int | None = None ,
306307 timeout : int | None = DEFAULT_TIMEOUT ,
307308 num_max_attempts : int | None = 1 ,
309+ user_project : str | None = None ,
308310 ) -> str | bytes :
309311 """
310312 Downloads a file from Google Cloud Storage.
@@ -320,6 +322,8 @@ def download(
320322 :param chunk_size: Blob chunk size.
321323 :param timeout: Request timeout in seconds.
322324 :param num_max_attempts: Number of attempts to download the file.
325+ :param user_project: The identifier of the Google Cloud project to bill for the request.
326+ Required for Requester Pays buckets.
323327 """
324328 # TODO: future improvement check file size before downloading,
325329 # to check for local space availability
@@ -330,7 +334,7 @@ def download(
330334 try :
331335 num_file_attempts += 1
332336 client = self .get_conn ()
333- bucket = client .bucket (bucket_name )
337+ bucket = client .bucket (bucket_name , user_project = user_project )
334338 blob = bucket .blob (blob_name = object_name , chunk_size = chunk_size )
335339
336340 if filename :
@@ -395,6 +399,7 @@ def provide_file(
395399 object_name : str | None = None ,
396400 object_url : str | None = None ,
397401 dir : str | None = None ,
402+ user_project : str | None = None ,
398403 ) -> Generator [IO [bytes ], None , None ]:
399404 """
400405 Downloads the file to a temporary directory and returns a file handle.
@@ -406,13 +411,20 @@ def provide_file(
406411 :param object_name: The object to fetch.
407412 :param object_url: File reference url. Must start with "gs: //"
408413 :param dir: The tmp sub directory to download the file to. (passed to NamedTemporaryFile)
414+ :param user_project: The identifier of the Google Cloud project to bill for the request.
415+ Required for Requester Pays buckets.
409416 :return: File handler
410417 """
411418 if object_name is None :
412419 raise ValueError ("Object name can not be empty" )
413420 _ , _ , file_name = object_name .rpartition ("/" )
414421 with NamedTemporaryFile (suffix = file_name , dir = dir ) as tmp_file :
415- self .download (bucket_name = bucket_name , object_name = object_name , filename = tmp_file .name )
422+ self .download (
423+ bucket_name = bucket_name ,
424+ object_name = object_name ,
425+ filename = tmp_file .name ,
426+ user_project = user_project ,
427+ )
416428 tmp_file .flush ()
417429 yield tmp_file
418430
@@ -423,6 +435,7 @@ def provide_file_and_upload(
423435 bucket_name : str = PROVIDE_BUCKET ,
424436 object_name : str | None = None ,
425437 object_url : str | None = None ,
438+ user_project : str | None = None ,
426439 ) -> Generator [IO [bytes ], None , None ]:
427440 """
428441 Creates temporary file, returns a file handle and uploads the files content on close.
@@ -433,6 +446,8 @@ def provide_file_and_upload(
433446 :param bucket_name: The bucket to fetch from.
434447 :param object_name: The object to fetch.
435448 :param object_url: File reference url. Must start with "gs: //"
449+ :param user_project: The identifier of the Google Cloud project to bill for the request.
450+ Required for Requester Pays buckets.
436451 :return: File handler
437452 """
438453 if object_name is None :
@@ -442,7 +457,12 @@ def provide_file_and_upload(
442457 with NamedTemporaryFile (suffix = file_name ) as tmp_file :
443458 yield tmp_file
444459 tmp_file .flush ()
445- self .upload (bucket_name = bucket_name , object_name = object_name , filename = tmp_file .name )
460+ self .upload (
461+ bucket_name = bucket_name ,
462+ object_name = object_name ,
463+ filename = tmp_file .name ,
464+ user_project = user_project ,
465+ )
446466
447467 def upload (
448468 self ,
@@ -458,6 +478,7 @@ def upload(
458478 num_max_attempts : int = 1 ,
459479 metadata : dict | None = None ,
460480 cache_control : str | None = None ,
481+ user_project : str | None = None ,
461482 ) -> None :
462483 """
463484 Uploads a local file or file data as string or bytes to Google Cloud Storage.
@@ -474,6 +495,8 @@ def upload(
474495 :param num_max_attempts: Number of attempts to try to upload the file.
475496 :param metadata: The metadata to be uploaded with the file.
476497 :param cache_control: Cache-Control metadata field.
498+ :param user_project: The identifier of the Google Cloud project to bill for the request.
499+ Required for Requester Pays buckets.
477500 """
478501
479502 def _call_with_retry (f : Callable [[], None ]) -> None :
@@ -506,7 +529,7 @@ def _call_with_retry(f: Callable[[], None]) -> None:
506529 continue
507530
508531 client = self .get_conn ()
509- bucket = client .bucket (bucket_name )
532+ bucket = client .bucket (bucket_name , user_project = user_project )
510533 blob = bucket .blob (blob_name = object_name , chunk_size = chunk_size )
511534
512535 if metadata :
@@ -596,7 +619,6 @@ def is_updated_after(self, bucket_name: str, object_name: str, ts: datetime) ->
596619 """
597620 blob_update_time = self .get_blob_update_time (bucket_name , object_name )
598621 if blob_update_time is not None :
599-
600622 if not ts .tzinfo :
601623 ts = ts .replace (tzinfo = timezone .utc )
602624 self .log .info ("Verify object date: %s > %s" , blob_update_time , ts )
@@ -618,7 +640,6 @@ def is_updated_between(
618640 """
619641 blob_update_time = self .get_blob_update_time (bucket_name , object_name )
620642 if blob_update_time is not None :
621-
622643 if not min_ts .tzinfo :
623644 min_ts = min_ts .replace (tzinfo = timezone .utc )
624645 if not max_ts .tzinfo :
@@ -639,7 +660,6 @@ def is_updated_before(self, bucket_name: str, object_name: str, ts: datetime) ->
639660 """
640661 blob_update_time = self .get_blob_update_time (bucket_name , object_name )
641662 if blob_update_time is not None :
642-
643663 if not ts .tzinfo :
644664 ts = ts .replace (tzinfo = timezone .utc )
645665 self .log .info ("Verify object date: %s < %s" , blob_update_time , ts )
@@ -681,16 +701,18 @@ def delete(self, bucket_name: str, object_name: str) -> None:
681701
682702 self .log .info ("Blob %s deleted." , object_name )
683703
684- def delete_bucket (self , bucket_name : str , force : bool = False ) -> None :
704+ def delete_bucket (self , bucket_name : str , force : bool = False , user_project : str | None = None ) -> None :
685705 """
686706 Delete a bucket object from the Google Cloud Storage.
687707
688708 :param bucket_name: name of the bucket which will be deleted
689709 :param force: false not allow to delete non empty bucket, set force=True
690710 allows to delete non empty bucket
711+ :param user_project: The identifier of the Google Cloud project to bill for the request.
712+ Required for Requester Pays buckets.
691713 """
692714 client = self .get_conn ()
693- bucket = client .bucket (bucket_name )
715+ bucket = client .bucket (bucket_name , user_project = user_project )
694716
695717 self .log .info ("Deleting %s bucket" , bucket_name )
696718 try :
@@ -707,6 +729,7 @@ def list(
707729 prefix : str | List [str ] | None = None ,
708730 delimiter : str | None = None ,
709731 match_glob : str | None = None ,
732+ user_project : str | None = None ,
710733 ):
711734 """
712735 List all objects from the bucket with the given a single prefix or multiple prefixes.
@@ -718,6 +741,8 @@ def list(
718741 :param delimiter: (Deprecated) filters objects based on the delimiter (for e.g '.csv')
719742 :param match_glob: (Optional) filters objects based on the glob pattern given by the string
720743 (e.g, ``'**/*/.json'``).
744+ :param user_project: The identifier of the Google Cloud project to bill for the request.
745+ Required for Requester Pays buckets.
721746 :return: a stream of object names matching the filtering criteria
722747 """
723748 if delimiter and delimiter != "/" :
@@ -739,6 +764,7 @@ def list(
739764 prefix = prefix_item ,
740765 delimiter = delimiter ,
741766 match_glob = match_glob ,
767+ user_project = user_project ,
742768 )
743769 )
744770 else :
@@ -750,6 +776,7 @@ def list(
750776 prefix = prefix ,
751777 delimiter = delimiter ,
752778 match_glob = match_glob ,
779+ user_project = user_project ,
753780 )
754781 )
755782 return objects
@@ -762,6 +789,7 @@ def _list(
762789 prefix : str | None = None ,
763790 delimiter : str | None = None ,
764791 match_glob : str | None = None ,
792+ user_project : str | None = None ,
765793 ) -> List :
766794 """
767795 List all objects from the bucket with the give string prefix in name.
@@ -773,10 +801,12 @@ def _list(
773801 :param delimiter: (Deprecated) filters objects based on the delimiter (for e.g '.csv')
774802 :param match_glob: (Optional) filters objects based on the glob pattern given by the string
775803 (e.g, ``'**/*/.json'``).
804+ :param user_project: The identifier of the Google Cloud project to bill for the request.
805+ Required for Requester Pays buckets.
776806 :return: a stream of object names matching the filtering criteria
777807 """
778808 client = self .get_conn ()
779- bucket = client .bucket (bucket_name )
809+ bucket = client .bucket (bucket_name , user_project = user_project )
780810
781811 ids = []
782812 page_token = None
0 commit comments