Skip to content

Python: Stop accessing private Azure SDK attributes in Azure AI Search connector#13971

Open
SergeyMenshykh wants to merge 5 commits intomicrosoft:mainfrom
SergeyMenshykh:fix/azure-search-private-attrs
Open

Python: Stop accessing private Azure SDK attributes in Azure AI Search connector#13971
SergeyMenshykh wants to merge 5 commits intomicrosoft:mainfrom
SergeyMenshykh:fix/azure-search-private-attrs

Conversation

@SergeyMenshykh
Copy link
Copy Markdown
Member

Motivation and Context

CI fails with AttributeError: 'SearchIndexClient' object has no attribute '_endpoint' when azure-search-documents resolves to 12.0.0 (released 2026-04-01). The 12.0.0 release migrated from AutoRest to TypeSpec code generation, removing private attributes _endpoint and _credential from SearchIndexClient.

CI uses uv sync -U which upgrades past the lockfile, pulling in 12.0.0 since pyproject.toml specifies >= 11.6.0b4 with no upper bound.

Description

Stop reading SearchIndexClient._endpoint and ._credential. Instead, store endpoint and credential as explicit fields on AzureAISearchStore and AzureAISearchCollection, and pass them directly when constructing SearchClient.

Changes:

  • _get_search_client() accepts explicit endpoint + credential params instead of extracting from SearchIndexClient private attrs
  • _resolve_credential() new helper extracted from _get_search_index_client() for reuse
  • AzureAISearchStore / AzureAISearchCollection store search_endpoint and search_credential as fields, thread them through construction
  • Tests updated to assert on public fields instead of private SDK attributes

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass with both azure-search-documents==11.7.0b2 and ==12.0.0
  • No breaking changes to public API

…h connector

Replace access to SearchIndexClient._endpoint and ._credential (removed in
azure-search-documents 12.0.0 TypeSpec migration) with explicit endpoint and
credential fields on AzureAISearchStore and AzureAISearchCollection.

- Refactor _get_search_client() to accept explicit endpoint + credential params
- Extract _resolve_credential() helper from _get_search_index_client()
- Add search_endpoint and search_credential fields to Store and Collection
- Add search_credential parameter to AzureAISearchCollection constructor
- Update tests to assert on public fields instead of private SDK attributes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 8, 2026 11:57
@SergeyMenshykh SergeyMenshykh requested a review from a team as a code owner May 8, 2026 11:57
@moonbox3 moonbox3 added the python Pull requests for the Python Semantic Kernel label May 8, 2026
@SergeyMenshykh SergeyMenshykh self-assigned this May 8, 2026
@SergeyMenshykh SergeyMenshykh moved this to In Review in Agent Framework May 8, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Python Azure AI Search vector store connector to avoid relying on private Azure SDK attributes (e.g., SearchIndexClient._endpoint / ._credential) that were removed in azure-search-documents==12.0.0, by threading endpoint and credential explicitly through the connector’s store/collection classes.

Changes:

  • Refactors _get_search_client() to take explicit endpoint + credential parameters rather than reading from SearchIndexClient internals.
  • Extracts credential selection into a reusable _resolve_credential() helper and updates index client creation to use it.
  • Stores search_endpoint / search_credential on AzureAISearchStore and AzureAISearchCollection, and updates unit tests to assert via these public fields rather than SDK private attributes.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
python/semantic_kernel/connectors/azure_ai_search.py Refactors client construction to stop depending on private Azure SDK fields; adds explicit endpoint/credential threading and _resolve_credential().
python/tests/unit/connectors/memory/test_azure_ai_search.py Updates tests to avoid checking SDK private attributes and adds coverage for _resolve_credential().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread python/semantic_kernel/connectors/azure_ai_search.py
@SergeyMenshykh SergeyMenshykh marked this pull request as draft May 8, 2026 12:07
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Reviewers: 3 | Confidence: 89% | Result: All clear

Reviewed: Correctness, Test Coverage, Design Approach


Automated review by SergeyMenshykh's agents

SergeyMenshykh and others added 3 commits May 8, 2026 13:50
Align with azure-search-documents 11.7.0b2 which no longer accepts
sync TokenCredential in async SearchClient and SearchIndexClient.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ent provided directly

When AzureAISearchStore was created with a pre-built search_index_client,
search_endpoint defaulted to empty string. get_collection() forwarded this
to AzureAISearchSettings which treated it as an explicit (invalid) endpoint,
preventing env var fallback and raising VectorStoreInitializationException.

Change search_endpoint default from empty string to None on both
AzureAISearchCollection and AzureAISearchStore so that KernelBaseSettings
correctly falls back to environment variables.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The default distance_function fixture uses cosine_similarity which was
never in Azure AI Search's DISTANCE_FUNCTION_MAP. Tests passed before
because MagicMock(spec=SearchIndex) satisfied isinstance() with SDK v11,
bypassing distance function validation. With SDK v12 the isinstance
check fails, exposing the incorrect default.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@moonbox3
Copy link
Copy Markdown
Collaborator

moonbox3 commented May 8, 2026

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
connectors
   azure_ai_search.py3273389%162–163, 223, 225–228, 230, 259, 261, 263, 360, 384–385, 465, 467, 481–482, 493, 521–522, 564, 586, 596, 608, 628–629, 724, 726, 728, 731, 849–850
TOTAL28606564880% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
3882 23 💤 0 ❌ 0 🔥 1m 53s ⏱️

@SergeyMenshykh SergeyMenshykh marked this pull request as ready for review May 8, 2026 13:45
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Reviewers: 4 | Confidence: 92%

✓ Correctness

The PR correctly eliminates access to private Azure SDK attributes (_endpoint, _credential) on SearchIndexClient by storing endpoint and credential as explicit fields. The credential/endpoint resolution logic is properly extracted into _resolve_credential(), and the fallback behavior when search_index_client is provided directly (without explicit endpoint/credential) works correctly because KernelBaseSettings.__init__ strips None kwargs (line 55 of kernel_pydantic.py), allowing Pydantic to fall back to environment variables. The TokenCredentialAsyncTokenCredential narrowing is correct since the connector exclusively uses async clients. No correctness issues found.

✓ Security Reliability

This PR correctly eliminates reliance on private Azure SDK attributes (_endpoint, _credential) that broke in azure-search-documents 12.0.0. The refactoring stores endpoint and credential as explicit fields, threads them through construction, and introduces a _resolve_credential helper. No blocking security or reliability issues found. The credential fields use Any typing on the Pydantic models, but since the existing search_client and search_index_client fields already store arbitrary SDK objects containing credentials, this doesn't change the risk surface. One minor observation: _resolve_credential is called twice with the same arguments in both AzureAISearchCollection.__init__ (third path) and AzureAISearchStore.__init__, which creates distinct AzureKeyCredential instances when resolved from api_key, but this has no practical security or reliability impact.

✓ Test Coverage

The PR properly migrates away from private Azure SDK attributes and adds tests for the new _resolve_credential helper and the get_collection path when search_index_client is provided directly. Two test coverage gaps stand out: (1) test_resolve_credential excludes AZURE_AI_SEARCH_API_KEY from the environment, so the api_key fallback branch — the most common production path — is never directly tested; (2) test_get_collection_with_provided_search_index_client verifies collection creation but doesn't assert that the collection's search_endpoint and search_credential are properly resolved from environment variables, which is central to the PR's purpose.

✓ Design Approach

The private-attribute removal is headed in the right direction, but one construction path still drops the explicit endpoint/credential state the PR is trying to preserve: AzureAISearchStore ignores caller-suplied connection arguments whenever a prebuilt search_index_client is injected, so get_collection() can still fall back to env-based resolution instead of using the values the caller already provided.


Automated review by SergeyMenshykh's agents

Comment thread python/semantic_kernel/connectors/azure_ai_search.py
When a caller passes a pre-built search_index_client alongside explicit
connection args, the endpoint and credential were not captured because
they were only resolved inside the 'if not search_index_client' branch.
This caused get_collection() to forward None values, falling back to
env vars instead of using the caller's explicit values.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Pull requests for the Python Semantic Kernel

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

3 participants