diff --git a/sdk/search/azure-search-documents/CHANGELOG.md b/sdk/search/azure-search-documents/CHANGELOG.md index f4603347136e..c60c85bdbb1b 100644 --- a/sdk/search/azure-search-documents/CHANGELOG.md +++ b/sdk/search/azure-search-documents/CHANGELOG.md @@ -10,7 +10,7 @@ ### Bugs Fixed -- Fixed the issue that `SearchIndexerSkillset`, `SearchField`, `SearchIndex`, `AnalyzeTextOptions`, `SearchResourceEncryptionKey`, `SynonymMap`, `SearchIndexerDataSourceConnection` could not be serialized. +- Fixed the issue that `SearchIndexerSkillset`, `SearchField`, `SearchIndex`, `AnalyzeTextOptions`, `SearchResourceEncryptionKey`, `SynonymMap`, `SearchIndexerDataSourceConnection` could not be serialized and `as_dict` did not work. ### Other Changes 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 28ede871d7c9..9a430dd553c3 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 @@ -205,7 +205,7 @@ def _to_generated(self) -> _SearchField: ) @classmethod - def _from_generated(cls, search_field): + def _from_generated(cls, search_field) -> Optional["SearchField"]: if not search_field: return None # pylint:disable=protected-access @@ -243,7 +243,7 @@ def serialize(self, keep_readonly: bool = False, **kwargs: Any) -> MutableMappin return self._to_generated().serialize(keep_readonly=keep_readonly, **kwargs) @classmethod - def deserialize(cls, data: Any, content_type: Optional[str] = None) -> "SearchField": + def deserialize(cls, data: Any, content_type: Optional[str] = None) -> Optional["SearchField"]: """Parse a str using the RestAPI syntax and return a SearchField instance. :param str data: A str using RestAPI structure. JSON by default. @@ -251,7 +251,55 @@ def deserialize(cls, data: Any, content_type: Optional[str] = None) -> "SearchFi :returns: A SearchField instance :raises: DeserializationError if something went wrong """ - return cls._from_generated(_SearchField.deserialize(data, content_type=content_type)) # type: ignore + return cls._from_generated(_SearchField.deserialize(data, content_type=content_type)) + + def as_dict(self, keep_readonly: bool = True, **kwargs: Any) -> MutableMapping[str, Any]: + """Return a dict that can be serialized using json.dump. + + :param bool keep_readonly: If you want to serialize the readonly attributes + :returns: A dict JSON compatible object + :rtype: dict + """ + return self._to_generated().as_dict(keep_readonly=keep_readonly, **kwargs) # type: ignore + + @classmethod + def from_dict( + cls, + data: Any, + content_type: Optional[str] = None, + ) -> Optional["SearchField"]: + """Parse a dict using given key extractor return a model. + + :param dict data: A dict using RestAPI structure + :param str content_type: JSON by default, set application/xml if XML. + :returns: A SearchField instance + :rtype: SearchField + :raises: DeserializationError if something went wrong + """ + return cls._from_generated(_SearchField.from_dict(data, content_type=content_type)) + + def __eq__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: True if all attributes are equal, else False + :rtype: bool + """ + if isinstance(other, self.__class__): + return self.__dict__ == other.__dict__ + return False + + def __ne__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: False if all attributes are equal, else True + :rtype: bool + """ + return not self.__eq__(other) + + def __str__(self) -> str: + return str(self.__dict__) def SimpleField( @@ -674,6 +722,54 @@ def deserialize(cls, data: Any, content_type: Optional[str] = None) -> "SearchIn """ return cls._from_generated(_SearchIndex.deserialize(data, content_type=content_type)) + def as_dict(self, keep_readonly: bool = True, **kwargs: Any) -> MutableMapping[str, Any]: + """Return a dict that can be serialized using json.dump. + + :param bool keep_readonly: If you want to serialize the readonly attributes + :returns: A dict JSON compatible object + :rtype: dict + """ + return self._to_generated().as_dict(keep_readonly=keep_readonly, **kwargs) # type: ignore + + @classmethod + def from_dict( + cls, + data: Any, + content_type: Optional[str] = None, + ) -> "SearchIndex": + """Parse a dict using given key extractor return a model. + + :param dict data: A dict using RestAPI structure + :param str content_type: JSON by default, set application/xml if XML. + :returns: A SearchIndex instance + :rtype: SearchIndex + :raises: DeserializationError if something went wrong + """ + return cls._from_generated(_SearchIndex.from_dict(data, content_type=content_type)) + + def __eq__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: True if all attributes are equal, else False + :rtype: bool + """ + if isinstance(other, self.__class__): + return self.__dict__ == other.__dict__ + return False + + def __ne__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: False if all attributes are equal, else True + :rtype: bool + """ + return not self.__eq__(other) + + def __str__(self) -> str: + return str(self.__dict__) + def pack_search_field(search_field: SearchField) -> _SearchField: if isinstance(search_field, dict): diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_models.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_models.py index 14d0ff763c5d..37c23e97fa48 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_models.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/models/_models.py @@ -1,3 +1,4 @@ +# pylint: disable=too-many-lines # ------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for @@ -141,6 +142,54 @@ def deserialize(cls, data: Any, content_type: Optional[str] = None) -> "SearchIn """ return cls._from_generated(_SearchIndexerSkillset.deserialize(data, content_type=content_type)) + def as_dict(self, keep_readonly: bool = True, **kwargs: Any) -> MutableMapping[str, Any]: + """Return a dict that can be serialized using json.dump. + + :param bool keep_readonly: If you want to serialize the readonly attributes + :returns: A dict JSON compatible object + :rtype: dict + """ + return self._to_generated().as_dict(keep_readonly=keep_readonly, **kwargs) # type: ignore + + @classmethod + def from_dict( + cls, + data: Any, + content_type: Optional[str] = None, + ) -> "SearchIndexerSkillset": + """Parse a dict using given key extractor return a model. + + :param dict data: A dict using RestAPI structure + :param str content_type: JSON by default, set application/xml if XML. + :returns: A SearchIndexerSkillset instance + :rtype: SearchIndexerSkillset + :raises: DeserializationError if something went wrong + """ + return cls._from_generated(_SearchIndexerSkillset.from_dict(data, content_type=content_type)) + + def __eq__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: True if all attributes are equal, else False + :rtype: bool + """ + if isinstance(other, self.__class__): + return self.__dict__ == other.__dict__ + return False + + def __ne__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: False if all attributes are equal, else True + :rtype: bool + """ + return not self.__eq__(other) + + def __str__(self) -> str: + return str(self.__dict__) + class EntityRecognitionSkillVersion(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Specifies the Entity Recognition skill version to use.""" @@ -465,6 +514,54 @@ def deserialize(cls, data: Any, content_type: Optional[str] = None) -> "AnalyzeT """ return cls._from_analyze_request(AnalyzeRequest.deserialize(data, content_type=content_type)) + def as_dict(self, keep_readonly: bool = True, **kwargs: Any) -> MutableMapping[str, Any]: + """Return a dict that can be serialized using json.dump. + + :param bool keep_readonly: If you want to serialize the readonly attributes + :returns: A dict JSON compatible object + :rtype: dict + """ + return self._to_analyze_request().as_dict(keep_readonly=keep_readonly, **kwargs) # type: ignore + + @classmethod + def from_dict( + cls, + data: Any, + content_type: Optional[str] = None, + ) -> "AnalyzeTextOptions": + """Parse a dict using given key extractor return a model. + + :param dict data: A dict using RestAPI structure + :param str content_type: JSON by default, set application/xml if XML. + :returns: A AnalyzeTextOptions instance + :rtype: AnalyzeTextOptions + :raises: DeserializationError if something went wrong + """ + return cls._from_analyze_request(AnalyzeRequest.from_dict(data, content_type=content_type)) + + def __eq__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: True if all attributes are equal, else False + :rtype: bool + """ + if isinstance(other, self.__class__): + return self.__dict__ == other.__dict__ + return False + + def __ne__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: False if all attributes are equal, else True + :rtype: bool + """ + return not self.__eq__(other) + + def __str__(self) -> str: + return str(self.__dict__) + class CustomAnalyzer(LexicalAnalyzer): """Allows you to take control over the process of converting text into indexable/searchable tokens. @@ -726,7 +823,7 @@ def _to_generated(self): ) @classmethod - def _from_generated(cls, search_resource_encryption_key): + def _from_generated(cls, search_resource_encryption_key) -> Optional["SearchResourceEncryptionKey"]: if not search_resource_encryption_key: return None if search_resource_encryption_key.access_credentials: @@ -752,7 +849,7 @@ def serialize(self, keep_readonly: bool = False, **kwargs: Any) -> MutableMappin return self._to_generated().serialize(keep_readonly=keep_readonly, **kwargs) # type: ignore @classmethod - def deserialize(cls, data: Any, content_type: Optional[str] = None) -> "SearchResourceEncryptionKey": + def deserialize(cls, data: Any, content_type: Optional[str] = None) -> Optional["SearchResourceEncryptionKey"]: """Parse a str using the RestAPI syntax and return a SearchResourceEncryptionKey instance. :param str data: A str using RestAPI structure. JSON by default. @@ -764,6 +861,54 @@ def deserialize(cls, data: Any, content_type: Optional[str] = None) -> "SearchRe _SearchResourceEncryptionKey.deserialize(data, content_type=content_type) ) + def as_dict(self, keep_readonly: bool = True, **kwargs: Any) -> MutableMapping[str, Any]: + """Return a dict that can be serialized using json.dump. + + :param bool keep_readonly: If you want to serialize the readonly attributes + :returns: A dict JSON compatible object + :rtype: dict + """ + return self._to_generated().as_dict(keep_readonly=keep_readonly, **kwargs) # type: ignore + + @classmethod + def from_dict( + cls, + data: Any, + content_type: Optional[str] = None, + ) -> Optional["SearchResourceEncryptionKey"]: + """Parse a dict using given key extractor return a model. + + :param dict data: A dict using RestAPI structure + :param str content_type: JSON by default, set application/xml if XML. + :returns: A SearchResourceEncryptionKey instance + :rtype: SearchResourceEncryptionKey + :raises: DeserializationError if something went wrong + """ + return cls._from_generated(_SearchResourceEncryptionKey.from_dict(data, content_type=content_type)) + + def __eq__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: True if all attributes are equal, else False + :rtype: bool + """ + if isinstance(other, self.__class__): + return self.__dict__ == other.__dict__ + return False + + def __ne__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: False if all attributes are equal, else True + :rtype: bool + """ + return not self.__eq__(other) + + def __str__(self) -> str: + return str(self.__dict__) + class SynonymMap: """Represents a synonym map definition. @@ -841,6 +986,54 @@ def deserialize(cls, data: Any, content_type: Optional[str] = None) -> "SynonymM """ return cls._from_generated(_SynonymMap.deserialize(data, content_type=content_type)) + def as_dict(self, keep_readonly: bool = True, **kwargs: Any) -> MutableMapping[str, Any]: + """Return a dict that can be serialized using json.dump. + + :param bool keep_readonly: If you want to serialize the readonly attributes + :returns: A dict JSON compatible object + :rtype: dict + """ + return self._to_generated().as_dict(keep_readonly=keep_readonly, **kwargs) # type: ignore + + @classmethod + def from_dict( + cls, + data: Any, + content_type: Optional[str] = None, + ) -> "SynonymMap": + """Parse a dict using given key extractor return a model. + + :param dict data: A dict using RestAPI structure + :param str content_type: JSON by default, set application/xml if XML. + :returns: A SynonymMap instance + :rtype: SynonymMap + :raises: DeserializationError if something went wrong + """ + return cls._from_generated(_SynonymMap.from_dict(data, content_type=content_type)) + + def __eq__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: True if all attributes are equal, else False + :rtype: bool + """ + if isinstance(other, self.__class__): + return self.__dict__ == other.__dict__ + return False + + def __ne__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: False if all attributes are equal, else True + :rtype: bool + """ + return not self.__eq__(other) + + def __str__(self) -> str: + return str(self.__dict__) + class SearchIndexerDataSourceConnection: """Represents a datasource connection definition, which can be used to configure an indexer. @@ -946,6 +1139,54 @@ def deserialize(cls, data: Any, content_type: Optional[str] = None) -> "SearchIn """ return cls._from_generated(_SearchIndexerDataSource.deserialize(data, content_type=content_type)) + def as_dict(self, keep_readonly: bool = True, **kwargs: Any) -> MutableMapping[str, Any]: + """Return a dict that can be serialized using json.dump. + + :param bool keep_readonly: If you want to serialize the readonly attributes + :returns: A dict JSON compatible object + :rtype: dict + """ + return self._to_generated().as_dict(keep_readonly=keep_readonly, **kwargs) # type: ignore + + @classmethod + def from_dict( + cls, + data: Any, + content_type: Optional[str] = None, + ) -> "SearchIndexerDataSourceConnection": + """Parse a dict using given key extractor return a model. + + :param dict data: A dict using RestAPI structure + :param str content_type: JSON by default, set application/xml if XML. + :returns: A SearchIndexerDataSourceConnection instance + :rtype: SearchIndexerDataSourceConnection + :raises: DeserializationError if something went wrong + """ + return cls._from_generated(_SearchIndexerDataSource.from_dict(data, content_type=content_type)) + + def __eq__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: True if all attributes are equal, else False + :rtype: bool + """ + if isinstance(other, self.__class__): + return self.__dict__ == other.__dict__ + return False + + def __ne__(self, other: Any) -> bool: + """Compare objects by comparing all attributes. + + :param Any other: the object to compare with + :returns: False if all attributes are equal, else True + :rtype: bool + """ + return not self.__eq__(other) + + def __str__(self) -> str: + return str(self.__dict__) + def pack_analyzer(analyzer): if not analyzer: diff --git a/sdk/search/azure-search-documents/tests/test_serialization.py b/sdk/search/azure-search-documents/tests/test_serialization.py index 44a1d81f2a0c..09a5f04caf32 100644 --- a/sdk/search/azure-search-documents/tests/test_serialization.py +++ b/sdk/search/azure-search-documents/tests/test_serialization.py @@ -77,3 +77,32 @@ def test_serialize_search_indexer_skillset(): serialized_skillset = skillset.serialize() skillset = SearchIndexerSkillset.deserialize(serialized_skillset) assert skillset + + +def test_serialize_search_index_dict(): + new_index_name = "hotels" + fields = [ + SimpleField(name="hotelId", type=SearchFieldDataType.String, key=True), + SimpleField(name="baseRate", type=SearchFieldDataType.Double), + SearchableField(name="description", type=SearchFieldDataType.String, collection=True), + SearchableField(name="hotelName", type=SearchFieldDataType.String), + ComplexField( + name="address", + fields=[ + SimpleField(name="streetAddress", type=SearchFieldDataType.String), + SimpleField(name="city", type=SearchFieldDataType.String), + SimpleField(name="state", type=SearchFieldDataType.String), + ], + collection=True, + ), + ] + cors_options = CorsOptions(allowed_origins=["*"], max_age_in_seconds=60) + scoring_profile = ScoringProfile(name="MyProfile") + scoring_profiles = [] + scoring_profiles.append(scoring_profile) + index = SearchIndex( + name=new_index_name, fields=fields, scoring_profiles=scoring_profiles, cors_options=cors_options + ) + search_index_serialized_dict = index.as_dict() + search_index = SearchIndex.from_dict(search_index_serialized_dict) + assert search_index