From b6b2b5b8c02928c9671a21c7de4531921e8d3d7b Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Tue, 6 Feb 2024 16:44:57 -0800 Subject: [PATCH 1/2] typing fixes. --- .../azure/search/documents/_search_client.py | 7 +- .../documents/aio/_search_client_async.py | 7 +- .../documents/indexes/_search_index_client.py | 4 +- .../indexes/_search_indexer_client.py | 25 +++- .../azure/search/documents/indexes/_utils.py | 2 +- .../indexes/aio/_search_index_client.py | 16 ++- .../indexes/aio/_search_indexer_client.py | 31 ++++- .../search/documents/indexes/models/_index.py | 113 ++++++++++++------ .../samples/sample_query_session.py | 1 - 9 files changed, 145 insertions(+), 61 deletions(-) diff --git a/sdk/search/azure-search-documents/azure/search/documents/_search_client.py b/sdk/search/azure-search-documents/azure/search/documents/_search_client.py index 7dadf398d89b..e0872a53d3ac 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/_search_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/_search_client.py @@ -292,6 +292,7 @@ def search( :keyword vector_filter_mode: Determines whether or not filters are applied before or after the vector search is performed. Default is 'preFilter'. Known values are: "postFilter" and "preFilter". :paramtype vector_filter_mode: str or VectorFilterMode + :return: List of search results. :rtype: SearchItemPaged[dict] .. admonition:: Example: @@ -429,7 +430,7 @@ def suggest( :keyword int top: The number of suggestions to retrieve. The value must be a number between 1 and 100. The default is 5. - :return: List of documents. + :return: List of suggestion results. :rtype: list[dict] .. admonition:: Example: @@ -474,6 +475,7 @@ def autocomplete( suggester_name: str, *, mode: Optional[Union[str, AutocompleteMode]] = None, + filter: Optional[str] = None, use_fuzzy_matching: Optional[bool] = None, highlight_post_tag: Optional[str] = None, highlight_pre_tag: Optional[str] = None, @@ -510,6 +512,7 @@ def autocomplete( terms. Target fields must be included in the specified suggester. :keyword int top: The number of auto-completed terms to retrieve. This must be a value between 1 and 100. The default is 5. + :return: List of auto-completion results. :rtype: list[dict] .. admonition:: Example: @@ -522,7 +525,7 @@ def autocomplete( :caption: Get a auto-completions. """ autocomplete_mode = mode - filter_arg = kwargs.pop("filter", None) + filter_arg = filter search_fields_str = ",".join(search_fields) if search_fields else None query = AutocompleteQuery( search_text=search_text, diff --git a/sdk/search/azure-search-documents/azure/search/documents/aio/_search_client_async.py b/sdk/search/azure-search-documents/azure/search/documents/aio/_search_client_async.py index f4f4624b01a5..f0728cb3751b 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/aio/_search_client_async.py +++ b/sdk/search/azure-search-documents/azure/search/documents/aio/_search_client_async.py @@ -296,6 +296,7 @@ async def search( vector search is performed. Default is 'preFilter'. Known values are: "postFilter" and "preFilter". :paramtype vector_filter_mode: str or VectorFilterMode :return: A list of documents (dicts) matching the specified search criteria. + :return: List of search results. :rtype: AsyncSearchItemPaged[dict] .. admonition:: Example: @@ -427,7 +428,7 @@ async def suggest( included in the results. :keyword int top: The number of suggestions to retrieve. The value must be a number between 1 and 100. The default is 5. - :return: List of documents. + :return: List of suggestion results. :rtype: list[dict] .. admonition:: Example: @@ -472,6 +473,7 @@ async def autocomplete( suggester_name: str, *, mode: Optional[Union[str, AutocompleteMode]] = None, + filter: Optional[str] = None, use_fuzzy_matching: Optional[bool] = None, highlight_post_tag: Optional[str] = None, highlight_pre_tag: Optional[str] = None, @@ -508,6 +510,7 @@ async def autocomplete( terms. Target fields must be included in the specified suggester. :keyword int top: The number of auto-completed terms to retrieve. This must be a value between 1 and 100. The default is 5. + :return: List of auto-completion results. :rtype: list[Dict] .. admonition:: Example: @@ -520,7 +523,7 @@ async def autocomplete( :caption: Get a auto-completions. """ autocomplete_mode = mode - filter_arg = kwargs.pop("filter", None) + filter_arg = filter search_fields_str = ",".join(search_fields) if search_fields else None query = AutocompleteQuery( search_text=search_text, diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/_search_index_client.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/_search_index_client.py index ef0548740e2c..f8008f614e16 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/_search_index_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/_search_index_client.py @@ -385,8 +385,8 @@ def delete_synonym_map( the SynonymMap model must be provided instead of the name. It is enough to provide the name of the synonym map to delete unconditionally. - :param name: The synonym map name or object to delete - :type name: str or ~azure.search.documents.indexes.models.SynonymMap + :param synonym_map: The synonym map name or object to delete + :type synonym_map: str or ~azure.search.documents.indexes.models.SynonymMap :keyword match_condition: The match condition to use upon the etag :paramtype match_condition: ~azure.core.MatchConditions diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/_search_indexer_client.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/_search_indexer_client.py index 79b8923fc69f..934c95650fd3 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/_search_indexer_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/_search_indexer_client.py @@ -111,6 +111,8 @@ def create_or_update_indexer( indexer: SearchIndexer, *, match_condition: MatchConditions = MatchConditions.Unconditionally, + skip_indexer_reset_requirement_for_cache: Optional[bool] = None, + disable_cache_reprocessing_change_detection: Optional[bool] = None, **kwargs: Any ) -> SearchIndexer: """Creates a new indexer or updates an indexer if it already exists. @@ -132,7 +134,13 @@ def create_or_update_indexer( kwargs.update(access_condition) name = indexer.name result = self._client.indexers.create_or_update( - indexer_name=name, indexer=indexer, prefer="return=representation", error_map=error_map, **kwargs + indexer_name=name, + indexer=indexer, + prefer="return=representation", + error_map=error_map, + skip_indexer_reset_requirement_for_cache=skip_indexer_reset_requirement_for_cache, + disable_cache_reprocessing_change_detection=disable_cache_reprocessing_change_detection, + **kwargs ) return result @@ -281,7 +289,12 @@ def reset_indexer(self, name: str, **kwargs: Any) -> None: @distributed_trace def reset_documents( - self, indexer: Union[str, SearchIndexer], keys_or_ids: DocumentKeysOrIds, **kwargs: Any + self, + indexer: Union[str, SearchIndexer], + keys_or_ids: DocumentKeysOrIds, + *, + overwrite: bool = False, + **kwargs: Any ) -> None: """Resets specific documents in the datasource to be selectively re-ingested by the indexer. @@ -302,7 +315,7 @@ def reset_documents( name = indexer.name # type: ignore except AttributeError: name = indexer - return self._client.indexers.reset_docs(name, **kwargs) + return self._client.indexers.reset_docs(name, overwrite=overwrite, **kwargs) @distributed_trace def get_indexer_status(self, name: str, **kwargs: Any) -> SearchIndexerStatus: @@ -358,6 +371,7 @@ def create_or_update_data_source_connection( data_source_connection: SearchIndexerDataSourceConnection, *, match_condition: MatchConditions = MatchConditions.Unconditionally, + skip_indexer_reset_requirement_for_cache: Optional[bool] = None, **kwargs: Any ) -> SearchIndexerDataSourceConnection: """Creates a new data source connection or updates a data source connection if it already exists. @@ -381,6 +395,7 @@ def create_or_update_data_source_connection( data_source=packed_data_source, prefer="return=representation", error_map=error_map, + skip_indexer_reset_requirement_for_cache=skip_indexer_reset_requirement_for_cache, **kwargs ) # pylint:disable=protected-access @@ -584,6 +599,8 @@ def create_or_update_skillset( skillset: SearchIndexerSkillset, *, match_condition: MatchConditions = MatchConditions.Unconditionally, + skip_indexer_reset_requirement_for_cache: Optional[bool] = None, + disable_cache_reprocessing_change_detection: Optional[bool] = None, **kwargs: Any ) -> SearchIndexerSkillset: # pylint:disable=protected-access @@ -614,6 +631,8 @@ def create_or_update_skillset( skillset=skillset_gen, prefer="return=representation", error_map=error_map, + skip_indexer_reset_requirement_for_cache=skip_indexer_reset_requirement_for_cache, + disable_cache_reprocessing_change_detection=disable_cache_reprocessing_change_detection, **kwargs ) return SearchIndexerSkillset._from_generated(result) # pylint:disable=protected-access diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/_utils.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/_utils.py index c93d0f579b27..bfe9a82a8357 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/_utils.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/_utils.py @@ -64,7 +64,7 @@ def get_access_conditions( error_map[412] = ResourceNotFoundError if match_condition == MatchConditions.IfMissing: error_map[412] = ResourceExistsError - return error_map, dict(if_match=if_match, if_none_match=if_none_match) + return error_map, {"if_match": if_match, "if_none_match": if_none_match} except AttributeError as ex: raise ValueError("Unable to get e_tag from the model") from ex diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/aio/_search_index_client.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/aio/_search_index_client.py index 1497095238a2..ea7926c72bef 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/aio/_search_index_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/aio/_search_index_client.py @@ -163,7 +163,13 @@ async def get_index_statistics(self, index_name: str, **kwargs: Any) -> MutableM return result.as_dict() @distributed_trace_async - async def delete_index(self, index: Union[str, SearchIndex], **kwargs: Any) -> None: + async def delete_index( + self, + index: Union[str, SearchIndex], + *, + match_condition: MatchConditions = MatchConditions.Unconditionally, + **kwargs: Any + ) -> None: """Deletes a search index and all the documents it contains. The model must be provided instead of the name to use the access conditions @@ -183,9 +189,7 @@ async def delete_index(self, index: Union[str, SearchIndex], **kwargs: Any) -> N :caption: Delete an index. """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - error_map, access_condition = get_access_conditions( - index, kwargs.pop("match_condition", MatchConditions.Unconditionally) - ) + error_map, access_condition = get_access_conditions(index, match_condition) kwargs.update(access_condition) try: index_name = index.name # type: ignore @@ -378,8 +382,8 @@ async def delete_synonym_map( the SynonymMap model must be provided instead of the name. It is enough to provide the name of the synonym map to delete unconditionally. - :param name: The synonym map name or object to delete - :type name: str or ~azure.search.documents.indexes.models.SynonymMap + :param synonym_map: The synonym map name or object to delete + :type synonym_map: str or ~azure.search.documents.indexes.models.SynonymMap :keyword match_condition: The match condition to use upon the etag :paramtype match_condition: ~azure.core.MatchConditions diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/aio/_search_indexer_client.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/aio/_search_indexer_client.py index b86ad04d954d..eb01c6c6a80d 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/aio/_search_indexer_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/aio/_search_indexer_client.py @@ -107,12 +107,16 @@ async def create_or_update_indexer( indexer: SearchIndexer, *, match_condition: MatchConditions = MatchConditions.Unconditionally, + skip_indexer_reset_requirement_for_cache: Optional[bool] = None, + disable_cache_reprocessing_change_detection: Optional[bool] = None, **kwargs: Any ) -> SearchIndexer: """Creates a new indexer or updates a indexer if it already exists. :param indexer: The definition of the indexer to create or update. :type indexer: ~azure.search.documents.indexes.models.SearchIndexer + :keyword match_condition: The match condition to use upon the etag + :paramtype match_condition: ~azure.core.MatchConditions :keyword skip_indexer_reset_requirement_for_cache: Ignores cache reset requirements. :paramtype skip_indexer_reset_requirement_for_cache: bool :keyword disable_cache_reprocessing_change_detection: Disables cache reprocessing change @@ -126,7 +130,13 @@ async def create_or_update_indexer( kwargs.update(access_condition) name = indexer.name result = await self._client.indexers.create_or_update( - indexer_name=name, indexer=indexer, prefer="return=representation", error_map=error_map, **kwargs + indexer_name=name, + indexer=indexer, + prefer="return=representation", + error_map=error_map, + skip_indexer_reset_requirement_for_cache=skip_indexer_reset_requirement_for_cache, + disable_cache_reprocessing_change_detection=disable_cache_reprocessing_change_detection, + **kwargs ) return result @@ -203,8 +213,8 @@ async def delete_indexer( must be provided instead of the name. It is enough to provide the name of the indexer to delete unconditionally. - :param name: The name or the indexer object to delete. - :type name: str or ~azure.search.documents.indexes.models.SearchIndexer + :param indexer: The name or the indexer object to delete. + :type indexer: str or ~azure.search.documents.indexes.models.SearchIndexer :keyword match_condition: The match condition to use upon the etag :paramtype match_condition: ~azure.core.MatchConditions @@ -266,7 +276,12 @@ async def reset_indexer(self, name: str, **kwargs: Any) -> None: @distributed_trace_async async def reset_documents( - self, indexer: Union[str, SearchIndexer], keys_or_ids: DocumentKeysOrIds, **kwargs: Any + self, + indexer: Union[str, SearchIndexer], + keys_or_ids: DocumentKeysOrIds, + *, + overwrite: bool = False, + **kwargs: Any ) -> None: """Resets specific documents in the datasource to be selectively re-ingested by the indexer. @@ -287,7 +302,7 @@ async def reset_documents( name = indexer.name # type: ignore except AttributeError: name = indexer - await self._client.indexers.reset_docs(name, **kwargs) + await self._client.indexers.reset_docs(name, overwrite=overwrite, **kwargs) return @distributed_trace_async @@ -343,6 +358,7 @@ async def create_or_update_data_source_connection( data_source_connection: SearchIndexerDataSourceConnection, *, match_condition: MatchConditions = MatchConditions.Unconditionally, + skip_indexer_reset_requirement_for_cache: Optional[bool] = None, **kwargs: Any ) -> SearchIndexerDataSourceConnection: """Creates a new data source connection or updates a data source connection if it already exists. @@ -369,6 +385,7 @@ async def create_or_update_data_source_connection( data_source=packed_data_source, prefer="return=representation", error_map=error_map, + skip_indexer_reset_requirement_for_cache=skip_indexer_reset_requirement_for_cache, **kwargs ) return SearchIndexerDataSourceConnection._from_generated(result) @@ -570,6 +587,8 @@ async def create_or_update_skillset( skillset: SearchIndexerSkillset, *, match_condition: MatchConditions = MatchConditions.Unconditionally, + skip_indexer_reset_requirement_for_cache: Optional[bool] = None, + disable_cache_reprocessing_change_detection: Optional[bool] = None, **kwargs: Any ) -> SearchIndexerSkillset: # pylint:disable=protected-access @@ -599,6 +618,8 @@ async def create_or_update_skillset( skillset=skillset_gen, prefer="return=representation", error_map=error_map, + skip_indexer_reset_requirement_for_cache=skip_indexer_reset_requirement_for_cache, + disable_cache_reprocessing_change_detection=disable_cache_reprocessing_change_detection, **kwargs ) return SearchIndexerSkillset._from_generated(result) # pylint:disable=protected-access diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_index.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_index.py index 0cd7e7689b6a..9f617bf28b4b 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_index.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_index.py @@ -3,7 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- -from typing import TYPE_CHECKING +from typing import Any, Dict, Union, List, Optional from .._generated import _serialization from ._edm import Collection, ComplexType, String @@ -11,6 +11,7 @@ SearchField as _SearchField, SearchIndex as _SearchIndex, PatternTokenizer as _PatternTokenizer, + LexicalAnalyzerName, ) from ._models import ( pack_analyzer, @@ -19,8 +20,6 @@ SearchResourceEncryptionKey, ) -if TYPE_CHECKING: - from typing import Any, Dict __all__ = ("ComplexField", "SearchableField", "SimpleField") @@ -265,8 +264,17 @@ def _from_generated(cls, search_field): ) -def SimpleField(**kw): - # type: (**Any) -> SearchField +def SimpleField( + *, + name: str, + type: str, + key: bool = False, + hidden: bool = False, + filterable: bool = False, + sortable: bool = False, + facetable: bool = False, + **kw # pylint:disable=unused-argument +) -> SearchField: """Configure a simple field for an Azure Search Index :keyword name: Required. The name of the field, which must be unique within the fields collection @@ -311,19 +319,38 @@ def SimpleField(**kw): on). Fields of type SearchFieldDataType.GeographyPoint or Collection(SearchFieldDataType.GeographyPoint) cannot be facetable. Default is False. :paramtype facetable: bool + :return: The search field object. + :rtype: SearchField """ - result = {"name": kw.get("name"), "type": kw.get("type")} # type: Dict[str, Any] - result["key"] = kw.get("key", False) - result["searchable"] = False - result["filterable"] = kw.get("filterable", False) - result["facetable"] = kw.get("facetable", False) - result["sortable"] = kw.get("sortable", False) - result["hidden"] = kw.get("hidden", False) + result: Dict[str, Any] = { + "name": name, + "type": type, + "key": key, + "searchable": False, + "filterable": filterable, + "facetable": facetable, + "sortable": sortable, + "hidden": hidden, + } return SearchField(**result) -def SearchableField(**kw): - # type: (**Any) -> SearchField +def SearchableField( + *, + name: str, + collection: bool = False, + key: bool = False, + hidden: bool = False, + searchable: bool = False, + filterable: bool = False, + sortable: bool = False, + facetable: bool = False, + analyzer_name: Optional[Union[str, LexicalAnalyzerName]] = None, + search_analyzer_name: Optional[Union[str, LexicalAnalyzerName]] = None, + index_analyzer_name: Optional[Union[str, LexicalAnalyzerName]] = None, + synonym_map_names: Optional[List[str]] = None, + **kw # pylint:disable=unused-argument +) -> SearchField: """Configure a searchable text field for an Azure Search Index :keyword name: Required. The name of the field, which must be unique within the fields collection @@ -438,29 +465,38 @@ def SearchableField(**kw): query terms targeting that field are expanded at query-time using the rules in the synonym map. This attribute can be changed on existing fields. :paramtype synonym_map_names: list[str] - + :return: The search field object. + :rtype: SearchField """ - typ = Collection(String) if kw.get("collection", False) else String - result = {"name": kw.get("name"), "type": typ} # type: Dict[str, Any] - result["key"] = kw.get("key", False) - result["searchable"] = kw.get("searchable", True) - result["filterable"] = kw.get("filterable", False) - result["facetable"] = kw.get("facetable", False) - result["sortable"] = kw.get("sortable", False) - result["hidden"] = kw.get("hidden", False) - if "analyzer_name" in kw: - result["analyzer_name"] = kw["analyzer_name"] - if "search_analyzer_name" in kw: - result["search_analyzer_name"] = kw["search_analyzer_name"] - if "index_analyzer_name" in kw: - result["index_analyzer_name"] = kw["index_analyzer_name"] - if "synonym_map_names" in kw: - result["synonym_map_names"] = kw["synonym_map_names"] + typ = Collection(String) if collection else String + result: Dict[str, Any] = { + "name": name, + "type": typ, + "key": key, + "searchable": searchable, + "filterable": filterable, + "facetable": facetable, + "sortable": sortable, + "hidden": hidden, + } + if analyzer_name: + result["analyzer_name"] = analyzer_name + if search_analyzer_name: + result["search_analyzer_name"] = search_analyzer_name + if index_analyzer_name: + result["index_analyzer_name"] = index_analyzer_name + if synonym_map_names: + result["synonym_map_names"] = synonym_map_names return SearchField(**result) -def ComplexField(**kw): - # type: (**Any) -> SearchField +def ComplexField( + *, + name: str, + collection: bool = False, + fields: Optional[List[SearchField]] = None, + **kw # pylint:disable=unused-argument +) -> SearchField: """Configure a Complex or Complex collection field for an Azure Search Index @@ -469,14 +505,13 @@ def ComplexField(**kw): :paramtype name: str :keyword collection: Whether this complex field is a collection (default False) :paramtype collection: bool - :paramtype type: str or ~azure.search.documents.indexes.models.DataType :keyword fields: A list of sub-fields - :paramtype fields: list[~azure.search.documents.indexes.models.Field] - + :paramtype fields: list[~azure.search.documents.indexes.models.SearchField] + :return: The search field object. + :rtype: SearchField """ - typ = Collection(ComplexType) if kw.get("collection", False) else ComplexType - result = {"name": kw.get("name"), "type": typ} # type: Dict[str, Any] - result["fields"] = kw.get("fields") + typ = Collection(ComplexType) if collection else ComplexType + result: Dict[str, Any] = {"name": name, "type": typ, "fields": fields} return SearchField(**result) diff --git a/sdk/search/azure-search-documents/samples/sample_query_session.py b/sdk/search/azure-search-documents/samples/sample_query_session.py index e7e127f93551..64e783ff636a 100644 --- a/sdk/search/azure-search-documents/samples/sample_query_session.py +++ b/sdk/search/azure-search-documents/samples/sample_query_session.py @@ -45,4 +45,3 @@ def query_session(): if __name__ == "__main__": query_session() - From c2ac24e77db15106bc3204096d2ed5ee1c7c6fde Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Tue, 6 Feb 2024 17:07:51 -0800 Subject: [PATCH 2/2] update --- .../azure/search/documents/indexes/models/_index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_index.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_index.py index 9f617bf28b4b..dd7c63205abc 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_index.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_index.py @@ -341,7 +341,7 @@ def SearchableField( collection: bool = False, key: bool = False, hidden: bool = False, - searchable: bool = False, + searchable: bool = True, filterable: bool = False, sortable: bool = False, facetable: bool = False,