Skip to content

Commit a64bcd4

Browse files
author
Alexandra Popova
committed
fix: choosing the most specific prefix for storage credentials
1 parent d98327c commit a64bcd4

1 file changed

Lines changed: 32 additions & 13 deletions

File tree

pyiceberg/catalog/rest/__init__.py

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,12 @@ def _response_to_table(self, identifier_tuple: Tuple[str, ...], table_response:
462462
io=self._load_file_io(
463463
{
464464
**table_response.metadata.properties,
465-
**self._get_credentials(table_response.storage_credentials, table_response.config),
465+
**self._get_credentials(
466+
table_response.storage_credentials,
467+
table_response.config,
468+
table_response.metadata_location,
469+
getattr(table_response.metadata, "location", None),
470+
),
466471
},
467472
table_response.metadata_location,
468473
),
@@ -478,25 +483,39 @@ def _response_to_staged_table(self, identifier_tuple: Tuple[str, ...], table_res
478483
io=self._load_file_io(
479484
{
480485
**table_response.metadata.properties,
481-
**self._get_credentials(table_response.storage_credentials, table_response.config),
486+
**self._get_credentials(
487+
table_response.storage_credentials,
488+
table_response.config,
489+
table_response.metadata_location,
490+
getattr(table_response.metadata, "location", None),
491+
),
482492
},
483493
table_response.metadata_location,
484494
),
485495
catalog=self,
486496
)
487497

488-
def _get_credentials(self, storage_credentials: List[StorageCredential], config: Properties) -> Properties:
489-
if storage_credentials:
490-
return self._get_storage_credentials(storage_credentials)
491-
return config
492-
493498
@staticmethod
494-
def _get_storage_credentials(storage_credentials: List[StorageCredential]) -> Properties:
495-
credentials: List[StorageCredential] = [sc for sc in storage_credentials if sc.prefix.startswith("s3")]
496-
if len(credentials) > 1:
497-
raise ValueError("Multiple S3 storage credentials found")
498-
elif len(credentials) == 1:
499-
return credentials[0].config
499+
def _get_credentials(
500+
storage_credentials: Optional[List[StorageCredential]],
501+
config: Properties,
502+
metadata_location: Optional[str],
503+
table_location: Optional[str],
504+
) -> Properties:
505+
if not storage_credentials:
506+
return config
507+
508+
target = metadata_location or table_location
509+
if not target:
510+
return config
511+
512+
# Choose the most specific (longest) matching prefix
513+
matching: List[StorageCredential] = [sc for sc in storage_credentials if target.startswith(sc.prefix)]
514+
if not matching:
515+
return config
516+
517+
selected = max(matching, key=lambda sc: len(sc.prefix))
518+
return selected.config
500519

501520
def _refresh_token(self) -> None:
502521
# Reactive token refresh is atypical - we should proactively refresh tokens in a separate thread

0 commit comments

Comments
 (0)