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