1717
1818import datetime
1919import glob
20+
21+ # Version detection and compatibility layer for google-cloud-storage v2/v3
22+ from importlib .metadata import version as get_version
2023import logging
2124import os
2225import pathlib
2326import tempfile
2427from typing import Optional , TYPE_CHECKING
28+ import warnings
2529
2630from google .auth import credentials as auth_credentials
2731from google .cloud import storage
32+ from packaging .version import Version
2833
2934from google .cloud .aiplatform import initializer
3035from google .cloud .aiplatform .utils import resource_manager_utils
3540_logger = logging .getLogger (__name__ )
3641
3742
43+ # Detect google-cloud-storage version once at module load
44+ try :
45+ _GCS_VERSION = Version (get_version ("google-cloud-storage" ))
46+ except Exception :
47+ # Fallback if version detection fails (should not happen in normal use)
48+ _GCS_VERSION = Version ("2.0.0" )
49+
50+ _USE_FROM_URI = _GCS_VERSION >= Version ("3.0.0" )
51+
52+ # Warn users on v2 about upcoming deprecation
53+ if _GCS_VERSION < Version ("3.0.0" ):
54+ warnings .warn (
55+ "Support for google-cloud-storage < 3.0.0 will be removed in a future"
56+ " version of google-cloud-aiplatform. Please upgrade to"
57+ " google-cloud-storage >= 3.0.0." ,
58+ FutureWarning ,
59+ stacklevel = 2 ,
60+ )
61+
62+
63+ def blob_from_uri (uri : str , client : storage .Client ) -> storage .Blob :
64+ """Create a Blob from a GCS URI, compatible with v2 and v3.
65+
66+ This function provides compatibility across google-cloud-storage versions:
67+ - v3.x: Uses Blob.from_uri()
68+ - v2.x: Uses Blob.from_string() (deprecated in v3)
69+
70+ Args:
71+ uri: GCS URI (e.g., 'gs://bucket/path/to/blob')
72+ client: Storage client instance
73+
74+ Returns:
75+ storage.Blob: Blob instance
76+ """
77+ if _USE_FROM_URI :
78+ return storage .Blob .from_uri (uri , client = client )
79+ else :
80+ return storage .Blob .from_string (uri , client = client )
81+
82+
83+ def bucket_from_uri (uri : str , client : storage .Client ) -> storage .Bucket :
84+ """Create a Bucket from a GCS URI, compatible with v2 and v3.
85+
86+ This function provides compatibility across google-cloud-storage versions:
87+ - v3.x: Uses Bucket.from_uri()
88+ - v2.x: Uses Bucket.from_string() (deprecated in v3)
89+
90+ Args:
91+ uri: GCS bucket URI (e.g., 'gs://bucket-name')
92+ client: Storage client instance
93+
94+ Returns:
95+ storage.Bucket: Bucket instance
96+ """
97+ if _USE_FROM_URI :
98+ return storage .Bucket .from_uri (uri , client = client )
99+ else :
100+ return storage .Bucket .from_string (uri , client = client )
101+
102+
38103def upload_to_gcs (
39104 source_path : str ,
40105 destination_uri : str ,
@@ -79,18 +144,18 @@ def upload_to_gcs(
79144 destination_file_uri = (
80145 destination_uri .rstrip ("/" ) + "/" + source_file_relative_posix_path
81146 )
82- _logger .debug (f'Uploading "{ source_file_path } " to "{ destination_file_uri } "' )
83- destination_blob = storage .Blob .from_string (
147+ _logger .debug (
148+ 'Uploading "%s" to "%s"' , source_file_path , destination_file_uri
149+ )
150+ destination_blob = blob_from_uri (
84151 destination_file_uri , client = storage_client
85152 )
86153 destination_blob .upload_from_filename (filename = source_file_path )
87154 else :
88155 source_file_path = source_path
89156 destination_file_uri = destination_uri
90- _logger .debug (f'Uploading "{ source_file_path } " to "{ destination_file_uri } "' )
91- destination_blob = storage .Blob .from_string (
92- destination_file_uri , client = storage_client
93- )
157+ _logger .debug ('Uploading "%s" to "%s"' , source_file_path , destination_file_uri )
158+ destination_blob = blob_from_uri (destination_file_uri , client = storage_client )
94159 destination_blob .upload_from_filename (filename = source_file_path )
95160
96161
@@ -234,7 +299,7 @@ def create_gcs_bucket_for_pipeline_artifacts_if_it_does_not_exist(
234299 credentials = credentials ,
235300 )
236301
237- pipelines_bucket = storage . Bucket . from_string (
302+ pipelines_bucket = bucket_from_uri (
238303 uri = output_artifacts_gcs_dir ,
239304 client = storage_client ,
240305 )
@@ -294,9 +359,9 @@ def download_file_from_gcs(
294359 credentials = credentials or initializer .global_config .credentials
295360
296361 storage_client = storage .Client (project = project , credentials = credentials )
297- source_blob = storage . Blob . from_string (source_file_uri , client = storage_client )
362+ source_blob = blob_from_uri (source_file_uri , client = storage_client )
298363
299- _logger .debug (f 'Downloading "{ source_file_uri } " to "{ destination_file_path } "' )
364+ _logger .debug ('Downloading "%s " to "%s"' , source_file_uri , destination_file_path )
300365
301366 source_blob .download_to_filename (filename = destination_file_path )
302367
@@ -354,13 +419,10 @@ def _upload_pandas_df_to_gcs(
354419 """Uploads the provided Pandas DataFrame to a GCS bucket.
355420
356421 Args:
357- df (pandas.DataFrame):
358- Required. The Pandas DataFrame to upload.
359- upload_gcs_path (str):
360- Required. The GCS path to upload the data file.
361- file_format (str):
362- Required. The format to export the DataFrame to. Currently
363- only JSONL is supported.
422+ df (pandas.DataFrame): Required. The Pandas DataFrame to upload.
423+ upload_gcs_path (str): Required. The GCS path to upload the data file.
424+ file_format (str): Required. The format to export the DataFrame to.
425+ Currently only JSONL is supported.
364426
365427 Raises:
366428 ValueError: When a file format other than JSONL is provided.
@@ -378,9 +440,9 @@ def _upload_pandas_df_to_gcs(
378440 project = initializer .global_config .project ,
379441 credentials = initializer .global_config .credentials ,
380442 )
381- storage . Blob . from_string (
382- uri = upload_gcs_path , client = storage_client
383- ). upload_from_filename ( filename = local_dataset_path )
443+ blob_from_uri ( uri = upload_gcs_path , client = storage_client ). upload_from_filename (
444+ filename = local_dataset_path
445+ )
384446
385447
386448def validate_gcs_path (gcs_path : str ) -> None :
0 commit comments