From 1a3c30b0ab9d5d0547966cbbd5a3de21691c1a22 Mon Sep 17 00:00:00 2001 From: Tim Smith Date: Sat, 17 Oct 2026 12:50:22 -0600 Subject: [PATCH] refactor(proxy): build the credential name index and keep-set immutably Follow the repo's functional conventions on the touched lines: a MappingProxyType built in one shot for the first-occurrence index, a frozenset for the names to keep, Sequence parameters and explicit None returns. --- .../litellm_core_utils/credential_accessor.py | 16 ++++++++-------- litellm/proxy/proxy_server.py | 8 +++----- .../unit/proxy/proxy_server/test_proxy_config.py | 5 ----- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/litellm/litellm_core_utils/credential_accessor.py b/litellm/litellm_core_utils/credential_accessor.py index f902ece8d48..763a430a5df 100644 --- a/litellm/litellm_core_utils/credential_accessor.py +++ b/litellm/litellm_core_utils/credential_accessor.py @@ -1,6 +1,7 @@ """Utils for accessing credentials.""" -from collections.abc import Mapping +from collections.abc import Mapping, Sequence +from types import MappingProxyType from typing import Final import litellm @@ -30,16 +31,15 @@ class CredentialAccessor: return {} if credential is None else dict(credential_api_key_secret_reference(credential.credential_values)) @staticmethod - def upsert_credentials(credentials: list[CredentialItem]): + def upsert_credentials(credentials: Sequence[CredentialItem]) -> None: """Add credentials to the list, replacing the first existing entry with the same name in place.""" - index_by_name: Final[dict[str, int]] = {} - for i, cred in enumerate(litellm.credential_list): - index_by_name.setdefault(cred.credential_name, i) + first_index_by_name: Final = MappingProxyType( + {cred.credential_name: i for i, cred in reversed(tuple(enumerate(litellm.credential_list)))} + ) for credential in credentials: - existing_index = index_by_name.get(credential.credential_name) - if existing_index is not None: - litellm.credential_list[existing_index] = credential + if credential.credential_name in first_index_by_name: + litellm.credential_list[first_index_by_name[credential.credential_name]] = credential else: litellm.credential_list.append(credential) diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index c939e72165c..522643204d1 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -9646,7 +9646,7 @@ class ProxyConfig: credential_object.credential_values = decrypted_credential_values return credential_object - async def delete_credentials(self, db_credentials: list[CredentialItem]): + async def delete_credentials(self, db_credentials: Sequence[CredentialItem]) -> None: """ Create all-up list of db credentials + local credentials Compare to the litellm.credential_list @@ -9657,10 +9657,8 @@ class ProxyConfig: credential_list: Final = self.load_credential_list(config=config) ## DELETE ## - names_to_keep: Final = {cred.credential_name for cred in db_credentials} | { - cred.credential_name for cred in credential_list - } - litellm.credential_list[:] = [cred for cred in litellm.credential_list if cred.credential_name in names_to_keep] + names_to_keep: Final = frozenset(cred.credential_name for cred in (*db_credentials, *credential_list)) + litellm.credential_list[:] = (cred for cred in litellm.credential_list if cred.credential_name in names_to_keep) async def get_credentials(self, prisma_client: PrismaClient): try: diff --git a/tests/unit/proxy/proxy_server/test_proxy_config.py b/tests/unit/proxy/proxy_server/test_proxy_config.py index 79f3f37062e..db043d178b5 100644 --- a/tests/unit/proxy/proxy_server/test_proxy_config.py +++ b/tests/unit/proxy/proxy_server/test_proxy_config.py @@ -2061,11 +2061,6 @@ def test_ProxyConfig_load_credential_list_invalid_entry_raises(): pc.load_credential_list({"credential_list": [{"missing_required": True}]}) -# --------------------------------------------------------------------------- -# ProxyConfig.delete_credentials -# --------------------------------------------------------------------------- - - def _credential(name: str) -> CredentialItem: return CredentialItem(credential_name=name, credential_values={"api_key": f"key-{name}"}, credential_info={})