From 6fc321d7cbd28566334ab9ab7c1b2c1013235826 Mon Sep 17 00:00:00 2001 From: Matt Gotteiner Date: Mon, 6 Jul 2026 13:48:31 -0700 Subject: [PATCH 1/4] fix(search-documents): restore indexes model compat exports Restore the preview compatibility exports for KnowledgeRetrievalOutputMode and KnowledgeRetrievalReasoningEffort from azure.search.documents.indexes.models, and add back supported SearchIndex serialize/deserialize round-trip helpers via the package patch layer. Add targeted regression coverage, changelog notes, and the API surface snapshot update. Fixes #47871 Fixes #47872 Fixes #47873 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../azure-search-documents/CHANGELOG.md | 3 ++ sdk/search/azure-search-documents/api.md | 32 ++++++++++++++++ .../azure-search-documents/api.metadata.yml | 2 +- .../search/documents/indexes/models/_patch.py | 37 ++++++++++++++++++- .../tests/_capabilities.py | 2 + .../tests/test_search_index_model.py | 29 +++++++++++++++ 6 files changed, 103 insertions(+), 2 deletions(-) diff --git a/sdk/search/azure-search-documents/CHANGELOG.md b/sdk/search/azure-search-documents/CHANGELOG.md index ddec13dd33b2..8d8f8b148b07 100644 --- a/sdk/search/azure-search-documents/CHANGELOG.md +++ b/sdk/search/azure-search-documents/CHANGELOG.md @@ -8,6 +8,9 @@ ### Bugs Fixed +- Restored `KnowledgeRetrievalOutputMode` and `KnowledgeRetrievalReasoningEffort` as public re-exports from `azure.search.documents.indexes.models`. +- Restored supported public `SearchIndex.serialize()` and `SearchIndex.deserialize()` round-trip helpers. + ### Other Changes ## 12.1.0b1 (2026-05-28) diff --git a/sdk/search/azure-search-documents/api.md b/sdk/search/azure-search-documents/api.md index 13f9dde66b56..c5280ad442aa 100644 --- a/sdk/search/azure-search-documents/api.md +++ b/sdk/search/azure-search-documents/api.md @@ -4188,6 +4188,25 @@ namespace azure.search.documents.indexes.models ) -> None: ... + class azure.search.documents.indexes.models.KnowledgeRetrievalOutputMode(str, Enum, metaclass=CaseInsensitiveEnumMeta): + ANSWER_SYNTHESIS = "answerSynthesis" + EXTRACTIVE_DATA = "extractiveData" + + + class azure.search.documents.indexes.models.KnowledgeRetrievalReasoningEffort(_Model): + kind: str + + @overload + def __init__( + self, + *, + kind: str + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + class azure.search.documents.indexes.models.KnowledgeBaseAzureOpenAIModel(KnowledgeBaseModel, discriminator='azureOpenAI'): azure_open_ai_parameters: AzureOpenAIVectorizerParameters kind: Literal[KnowledgeBaseModelKind.AZURE_OPEN_AI] @@ -5854,6 +5873,19 @@ namespace azure.search.documents.indexes.models @overload def __init__(self, mapping: Mapping[str, Any]) -> None: ... + @classmethod + def deserialize( + cls, + data: Any, + content_type: Optional[str] = None + ) -> Self: ... + + def serialize( + self, + keep_readonly: bool = False, + **kwargs: Any + ) -> Any: ... + class azure.search.documents.indexes.models.SearchIndexFieldReference(_Model): name: str diff --git a/sdk/search/azure-search-documents/api.metadata.yml b/sdk/search/azure-search-documents/api.metadata.yml index b5f806f0ac36..27e0b1980f8f 100644 --- a/sdk/search/azure-search-documents/api.metadata.yml +++ b/sdk/search/azure-search-documents/api.metadata.yml @@ -1,3 +1,3 @@ -apiMdSha256: cf9b5548f872667463b76b7b872cc6b9083f419238d4b4df3bc2410ad0d64c8b +apiMdSha256: 896df7d7f6f8b9614be3ad5b11fab8edbc8cfd0fbab80a5279763db0897f9e6f parserVersion: 0.3.28 pythonVersion: 3.12.13 diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_patch.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_patch.py index 00e98e8b9b76..872101fa8b5e 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_patch.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_patch.py @@ -8,11 +8,15 @@ Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ -from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Union, overload +import json +from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Type, TypeVar, Union, overload from ._models import SearchField as _SearchField +from ._models import SearchIndex as _SearchIndex from ._models import SearchIndexerDataSourceConnection as _SearchIndexerDataSourceConnection from ._models import KnowledgeBase as _KnowledgeBase from ._models import SearchResourceEncryptionKey as _SearchResourceEncryptionKey +from ...knowledgebases.models._enums import KnowledgeRetrievalOutputMode +from ...knowledgebases.models._models import KnowledgeRetrievalReasoningEffort from ._enums import ( LexicalAnalyzerName, SearchFieldDataType as _SearchFieldDataType, @@ -30,6 +34,27 @@ from ._enums import SearchIndexerDataSourceType +_T = TypeVar("_T", bound="_PublicRoundTripMixin") + + +class _PublicRoundTripMixin: + """Restore supported public round-trip helpers for compatibility.""" + + def serialize(self, keep_readonly: bool = False, **kwargs: Any) -> Any: + """Return the JSON that would be sent to the service from this model.""" + + _ = kwargs + return self.as_dict(exclude_readonly=not keep_readonly) # type: ignore[attr-defined] + + @classmethod + def deserialize(cls: Type[_T], data: Any, content_type: Optional[str] = None) -> _T: + """Parse RestAPI-shaped data and return a model instance.""" + + if isinstance(data, (str, bytes, bytearray)) and content_type != "application/xml": + data = json.loads(data) + return cls(data) + + class SearchField(_SearchField): """Represents a field in an index definition, which describes the name, data type, and search behavior of a field. @@ -147,6 +172,13 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) +class SearchIndex(_PublicRoundTripMixin, _SearchIndex): + """Represents a search index definition with public round-trip helpers.""" + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + class KnowledgeBase(_KnowledgeBase): """Represents a knowledge base definition.""" @@ -451,8 +483,11 @@ def ComplexField( __all__: list[str] = [ "KnowledgeBase", + "KnowledgeRetrievalOutputMode", + "KnowledgeRetrievalReasoningEffort", "SearchField", "SearchFieldDataType", + "SearchIndex", "SearchIndexerDataSourceConnection", "SearchResourceEncryptionKey", "SimpleField", diff --git a/sdk/search/azure-search-documents/tests/_capabilities.py b/sdk/search/azure-search-documents/tests/_capabilities.py index 88862c6b9be3..98d95875887a 100644 --- a/sdk/search/azure-search-documents/tests/_capabilities.py +++ b/sdk/search/azure-search-documents/tests/_capabilities.py @@ -109,6 +109,8 @@ def _model_capabilities() -> Mapping[str, Mapping[str, Any]]: f"{_KBM}.KnowledgeRetrievalLowReasoningEffort", f"{_KBM}.KnowledgeRetrievalMediumReasoningEffort", f"{_KBM}.KnowledgeRetrievalOutputMode", + f"{_IM}.KnowledgeRetrievalOutputMode", + f"{_IM}.KnowledgeRetrievalReasoningEffort", f"{_KBM}.KnowledgeBaseModelQueryPlanningActivityRecord", f"{_KBM}.KnowledgeBaseModelAnswerSynthesisActivityRecord", f"{_KBM}.KnowledgeBaseModelWebSummarizationActivityRecord", diff --git a/sdk/search/azure-search-documents/tests/test_search_index_model.py b/sdk/search/azure-search-documents/tests/test_search_index_model.py index 2281186ae7bc..ec907abe36fb 100644 --- a/sdk/search/azure-search-documents/tests/test_search_index_model.py +++ b/sdk/search/azure-search-documents/tests/test_search_index_model.py @@ -8,11 +8,14 @@ from azure.search.documents.indexes.models import ( ComplexField, + KnowledgeRetrievalOutputMode, + KnowledgeRetrievalReasoningEffort, SearchFieldDataType, SearchIndex, SearchableField, SimpleField, ) +from tests._capabilities import require_capability INDEX_NAME = "hotels" @@ -97,3 +100,29 @@ def test_search_index_round_trips_helper_field_wire_shape(self): assert index.fields[2].analyzer_name == "en.lucene" assert index.fields[3].type == "Collection(Edm.String)" assert index.fields[4].fields[1].name == "State" + + def test_search_index_exposes_public_round_trip_helpers(self): + index = SearchIndex(name=INDEX_NAME, fields=create_hotel_fields(), e_tag="abc123") + + serialized = index.serialize() + round_tripped = SearchIndex.deserialize(serialized) + + assert serialized == index.as_dict() + assert isinstance(round_tripped, SearchIndex) + assert round_tripped.as_dict() == index.as_dict() + + def test_indexes_models_reexports_knowledge_retrieval_types(self): + require_capability( + "azure.search.documents.indexes.models.KnowledgeRetrievalOutputMode", + "azure.search.documents.indexes.models.KnowledgeRetrievalReasoningEffort", + ) + + from azure.search.documents.knowledgebases.models import ( + KnowledgeRetrievalOutputMode as KnowledgeRetrievalOutputModeFromKnowledgeBases, + ) + from azure.search.documents.knowledgebases.models import ( + KnowledgeRetrievalReasoningEffort as KnowledgeRetrievalReasoningEffortFromKnowledgeBases, + ) + + assert KnowledgeRetrievalOutputMode is KnowledgeRetrievalOutputModeFromKnowledgeBases + assert KnowledgeRetrievalReasoningEffort is KnowledgeRetrievalReasoningEffortFromKnowledgeBases From 8a0c265b0715cbb0b9dce2ede78aa6622e5bcab5 Mon Sep 17 00:00:00 2001 From: Matt Gotteiner Date: Mon, 6 Jul 2026 14:31:56 -0700 Subject: [PATCH 2/4] fix(search-documents): use local capability import in tests The isolated CI package test jobs do not expose a top-level tests package, so importing tests._capabilities caused collection-time ModuleNotFoundError across the PR matrix. Use the package-local _capabilities import instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../azure-search-documents/tests/test_search_index_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/search/azure-search-documents/tests/test_search_index_model.py b/sdk/search/azure-search-documents/tests/test_search_index_model.py index ec907abe36fb..d6f93689f590 100644 --- a/sdk/search/azure-search-documents/tests/test_search_index_model.py +++ b/sdk/search/azure-search-documents/tests/test_search_index_model.py @@ -15,7 +15,7 @@ SearchableField, SimpleField, ) -from tests._capabilities import require_capability +from _capabilities import require_capability INDEX_NAME = "hotels" From c13d2fe94b2531960696de199c7a57465695261e Mon Sep 17 00:00:00 2001 From: Matt Gotteiner Date: Mon, 6 Jul 2026 14:57:08 -0700 Subject: [PATCH 3/4] fix(search-documents): inline SearchIndex round-trip helpers Inline the public SearchIndex serialize/deserialize helpers onto SearchIndex instead of a private mixin to avoid the remaining docs/build CI failure while preserving the compatibility surface. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../search/documents/indexes/models/_patch.py | 39 ++++++++----------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_patch.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_patch.py index 872101fa8b5e..c04142577d54 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_patch.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_patch.py @@ -9,7 +9,7 @@ """ import json -from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Type, TypeVar, Union, overload +from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Union, overload from ._models import SearchField as _SearchField from ._models import SearchIndex as _SearchIndex from ._models import SearchIndexerDataSourceConnection as _SearchIndexerDataSourceConnection @@ -34,27 +34,6 @@ from ._enums import SearchIndexerDataSourceType -_T = TypeVar("_T", bound="_PublicRoundTripMixin") - - -class _PublicRoundTripMixin: - """Restore supported public round-trip helpers for compatibility.""" - - def serialize(self, keep_readonly: bool = False, **kwargs: Any) -> Any: - """Return the JSON that would be sent to the service from this model.""" - - _ = kwargs - return self.as_dict(exclude_readonly=not keep_readonly) # type: ignore[attr-defined] - - @classmethod - def deserialize(cls: Type[_T], data: Any, content_type: Optional[str] = None) -> _T: - """Parse RestAPI-shaped data and return a model instance.""" - - if isinstance(data, (str, bytes, bytearray)) and content_type != "application/xml": - data = json.loads(data) - return cls(data) - - class SearchField(_SearchField): """Represents a field in an index definition, which describes the name, data type, and search behavior of a field. @@ -172,12 +151,26 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class SearchIndex(_PublicRoundTripMixin, _SearchIndex): +class SearchIndex(_SearchIndex): """Represents a search index definition with public round-trip helpers.""" def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) + def serialize(self, keep_readonly: bool = False, **kwargs: Any) -> Any: + """Return the JSON that would be sent to the service from this model.""" + + _ = kwargs + return self.as_dict(exclude_readonly=not keep_readonly) + + @classmethod + def deserialize(cls, data: Any, content_type: Optional[str] = None): + """Parse RestAPI-shaped data and return a model instance.""" + + if isinstance(data, (str, bytes, bytearray)) and content_type != "application/xml": + data = json.loads(data) + return cls(data) + class KnowledgeBase(_KnowledgeBase): """Represents a knowledge base definition.""" From 564fd29ddd9635eb6994427b0b9589f157fe4ac4 Mon Sep 17 00:00:00 2001 From: Matt Gotteiner Date: Mon, 6 Jul 2026 15:21:18 -0700 Subject: [PATCH 4/4] fix(search-documents): avoid docs and pylint CI regressions Use docs-safe compatibility wrapper types for KnowledgeRetrievalOutputMode and KnowledgeRetrievalReasoningEffort so Sphinx does not index the same knowledgebases symbols twice, and add the required docstrings for the SearchIndex round-trip helpers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../search/documents/indexes/models/_patch.py | 36 ++++++++++++++++--- .../tests/test_search_index_model.py | 6 ++-- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_patch.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_patch.py index c04142577d54..3b61550bbbcd 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_patch.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_patch.py @@ -9,14 +9,15 @@ """ import json +from enum import Enum from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Union, overload +from azure.core import CaseInsensitiveEnumMeta from ._models import SearchField as _SearchField from ._models import SearchIndex as _SearchIndex from ._models import SearchIndexerDataSourceConnection as _SearchIndexerDataSourceConnection from ._models import KnowledgeBase as _KnowledgeBase from ._models import SearchResourceEncryptionKey as _SearchResourceEncryptionKey -from ...knowledgebases.models._enums import KnowledgeRetrievalOutputMode -from ...knowledgebases.models._models import KnowledgeRetrievalReasoningEffort +from ...knowledgebases.models._models import KnowledgeRetrievalReasoningEffort as _KnowledgeRetrievalReasoningEffort from ._enums import ( LexicalAnalyzerName, SearchFieldDataType as _SearchFieldDataType, @@ -158,20 +159,47 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) def serialize(self, keep_readonly: bool = False, **kwargs: Any) -> Any: - """Return the JSON that would be sent to the service from this model.""" + """ + Return the JSON that would be sent to the service from this model. + + :param bool keep_readonly: Whether to include readonly properties in the serialized payload. + :return: A JSON-serializable representation of this model. + :rtype: Any + """ _ = kwargs return self.as_dict(exclude_readonly=not keep_readonly) @classmethod def deserialize(cls, data: Any, content_type: Optional[str] = None): - """Parse RestAPI-shaped data and return a model instance.""" + """ + Parse RestAPI-shaped data and return a model instance. + + :param Any data: The serialized payload to deserialize. + :param str content_type: The payload content type. JSON is assumed unless XML is specified. + :return: A deserialized ``SearchIndex`` instance. + :rtype: ~azure.search.documents.indexes.models.SearchIndex + """ if isinstance(data, (str, bytes, bytearray)) and content_type != "application/xml": data = json.loads(data) return cls(data) +class KnowledgeRetrievalOutputMode(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """Compatibility export for knowledge retrieval output modes.""" + + ANSWER_SYNTHESIS = "answerSynthesis" + EXTRACTIVE_DATA = "extractiveData" + + +class KnowledgeRetrievalReasoningEffort(_KnowledgeRetrievalReasoningEffort): + """Compatibility export for knowledge retrieval reasoning effort.""" + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + class KnowledgeBase(_KnowledgeBase): """Represents a knowledge base definition.""" diff --git a/sdk/search/azure-search-documents/tests/test_search_index_model.py b/sdk/search/azure-search-documents/tests/test_search_index_model.py index d6f93689f590..399227b9d3af 100644 --- a/sdk/search/azure-search-documents/tests/test_search_index_model.py +++ b/sdk/search/azure-search-documents/tests/test_search_index_model.py @@ -124,5 +124,7 @@ def test_indexes_models_reexports_knowledge_retrieval_types(self): KnowledgeRetrievalReasoningEffort as KnowledgeRetrievalReasoningEffortFromKnowledgeBases, ) - assert KnowledgeRetrievalOutputMode is KnowledgeRetrievalOutputModeFromKnowledgeBases - assert KnowledgeRetrievalReasoningEffort is KnowledgeRetrievalReasoningEffortFromKnowledgeBases + assert KnowledgeRetrievalOutputMode.EXTRACTIVE_DATA == ( + KnowledgeRetrievalOutputModeFromKnowledgeBases.EXTRACTIVE_DATA + ) + assert issubclass(KnowledgeRetrievalReasoningEffort, KnowledgeRetrievalReasoningEffortFromKnowledgeBases)