@@ -3113,6 +3113,67 @@ def test_resolve_storage_credentials_empty() -> None:
31133113 assert RestCatalog ._resolve_storage_credentials ([], None ) == {}
31143114
31153115
3116+ def test_resolve_storage_credentials_skips_hadoop_only () -> None :
3117+ from pyiceberg .catalog .rest .scan_planning import StorageCredential
3118+
3119+ # The longer fs.* prefix would win a blind longest-match; the filter drops it.
3120+ credentials = [
3121+ StorageCredential (prefix = "s3://warehouse/jindo" , config = {"fs.s3.access-key" : "hadoop-k" }),
3122+ StorageCredential (prefix = "s3://warehouse" , config = {"s3.access-key-id" : "native-k" }),
3123+ ]
3124+ result = RestCatalog ._resolve_storage_credentials (credentials , "s3://warehouse/jindo/table/data" )
3125+ assert result == {"s3.access-key-id" : "native-k" }
3126+
3127+
3128+ def test_resolve_storage_credentials_mixed_prefix_namespaces_preserved () -> None :
3129+ from pyiceberg .catalog .rest .scan_planning import StorageCredential
3130+
3131+ credentials = [
3132+ StorageCredential (prefix = "gs" , config = {"gs.oauth2.token" : "tok" }),
3133+ StorageCredential (prefix = "s3" , config = {"s3.access-key-id" : "native-k" }),
3134+ ]
3135+ result = RestCatalog ._resolve_storage_credentials (credentials , "gs://bucket/path" )
3136+ assert result == {"gs.oauth2.token" : "tok" }
3137+
3138+
3139+ def test_resolve_storage_credentials_all_hadoop_only_returns_empty () -> None :
3140+ from pyiceberg .catalog .rest .scan_planning import StorageCredential
3141+
3142+ credentials = [
3143+ StorageCredential (prefix = "custom" , config = {"fs.custom.access-key" : "hadoop-k" }),
3144+ ]
3145+ assert RestCatalog ._resolve_storage_credentials (credentials , "custom://bucket/path" ) == {}
3146+
3147+
3148+ def test_resolve_storage_credentials_root_prefix_fallback_for_s3_compatible_scheme () -> None :
3149+ from pyiceberg .catalog .rest .scan_planning import StorageCredential
3150+
3151+ # oss:// is routed through pyarrow's S3FileSystem, so ROOT_PREFIX "s3" applies.
3152+ credentials = [
3153+ StorageCredential (prefix = "s3" , config = {"s3.access-key-id" : "native-k" }),
3154+ ]
3155+ result = RestCatalog ._resolve_storage_credentials (credentials , "oss://bucket/path" )
3156+ assert result == {"s3.access-key-id" : "native-k" }
3157+
3158+
3159+ def test_resolve_storage_credentials_root_prefix_fallback_respects_consumable () -> None :
3160+ from pyiceberg .catalog .rest .scan_planning import StorageCredential
3161+
3162+ credentials = [
3163+ StorageCredential (prefix = "s3" , config = {"fs.s3.access-key" : "hadoop-k" }),
3164+ ]
3165+ assert RestCatalog ._resolve_storage_credentials (credentials , "s3://bucket/path" ) == {}
3166+
3167+
3168+ def test_resolve_storage_credentials_fallback_skipped_for_non_s3_scheme () -> None :
3169+ from pyiceberg .catalog .rest .scan_planning import StorageCredential
3170+
3171+ credentials = [
3172+ StorageCredential (prefix = "s3" , config = {"s3.access-key-id" : "native-k" }),
3173+ ]
3174+ assert RestCatalog ._resolve_storage_credentials (credentials , "gs://bucket/path" ) == {}
3175+
3176+
31163177def test_load_table_with_storage_credentials (rest_mock : Mocker , example_table_metadata_with_snapshot_v1 : dict [str , Any ]) -> None :
31173178 metadata_location = "s3://warehouse/database/table/metadata/00001.metadata.json"
31183179 rest_mock .get (
0 commit comments