@@ -2844,6 +2844,67 @@ def test_resolve_storage_credentials_empty() -> None:
28442844 assert RestCatalog ._resolve_storage_credentials ([], None ) == {}
28452845
28462846
2847+ def test_resolve_storage_credentials_skips_hadoop_only () -> None :
2848+ from pyiceberg .catalog .rest .scan_planning import StorageCredential
2849+
2850+ # The longer fs.* prefix would win a blind longest-match; the filter drops it.
2851+ credentials = [
2852+ StorageCredential (prefix = "s3://warehouse/jindo" , config = {"fs.s3.access-key" : "hadoop-k" }),
2853+ StorageCredential (prefix = "s3://warehouse" , config = {"s3.access-key-id" : "native-k" }),
2854+ ]
2855+ result = RestCatalog ._resolve_storage_credentials (credentials , "s3://warehouse/jindo/table/data" )
2856+ assert result == {"s3.access-key-id" : "native-k" }
2857+
2858+
2859+ def test_resolve_storage_credentials_mixed_prefix_namespaces_preserved () -> None :
2860+ from pyiceberg .catalog .rest .scan_planning import StorageCredential
2861+
2862+ credentials = [
2863+ StorageCredential (prefix = "gs" , config = {"gs.oauth2.token" : "tok" }),
2864+ StorageCredential (prefix = "s3" , config = {"s3.access-key-id" : "native-k" }),
2865+ ]
2866+ result = RestCatalog ._resolve_storage_credentials (credentials , "gs://bucket/path" )
2867+ assert result == {"gs.oauth2.token" : "tok" }
2868+
2869+
2870+ def test_resolve_storage_credentials_all_hadoop_only_returns_empty () -> None :
2871+ from pyiceberg .catalog .rest .scan_planning import StorageCredential
2872+
2873+ credentials = [
2874+ StorageCredential (prefix = "custom" , config = {"fs.custom.access-key" : "hadoop-k" }),
2875+ ]
2876+ assert RestCatalog ._resolve_storage_credentials (credentials , "custom://bucket/path" ) == {}
2877+
2878+
2879+ def test_resolve_storage_credentials_root_prefix_fallback_for_s3_compatible_scheme () -> None :
2880+ from pyiceberg .catalog .rest .scan_planning import StorageCredential
2881+
2882+ # oss:// is routed through pyarrow's S3FileSystem, so ROOT_PREFIX "s3" applies.
2883+ credentials = [
2884+ StorageCredential (prefix = "s3" , config = {"s3.access-key-id" : "native-k" }),
2885+ ]
2886+ result = RestCatalog ._resolve_storage_credentials (credentials , "oss://bucket/path" )
2887+ assert result == {"s3.access-key-id" : "native-k" }
2888+
2889+
2890+ def test_resolve_storage_credentials_root_prefix_fallback_respects_consumable () -> None :
2891+ from pyiceberg .catalog .rest .scan_planning import StorageCredential
2892+
2893+ credentials = [
2894+ StorageCredential (prefix = "s3" , config = {"fs.s3.access-key" : "hadoop-k" }),
2895+ ]
2896+ assert RestCatalog ._resolve_storage_credentials (credentials , "s3://bucket/path" ) == {}
2897+
2898+
2899+ def test_resolve_storage_credentials_fallback_skipped_for_non_s3_scheme () -> None :
2900+ from pyiceberg .catalog .rest .scan_planning import StorageCredential
2901+
2902+ credentials = [
2903+ StorageCredential (prefix = "s3" , config = {"s3.access-key-id" : "native-k" }),
2904+ ]
2905+ assert RestCatalog ._resolve_storage_credentials (credentials , "gs://bucket/path" ) == {}
2906+
2907+
28472908def test_load_table_with_storage_credentials (rest_mock : Mocker , example_table_metadata_with_snapshot_v1 : dict [str , Any ]) -> None :
28482909 metadata_location = "s3://warehouse/database/table/metadata/00001.metadata.json"
28492910 rest_mock .get (
0 commit comments