From d58066c49f16a5399ff7ef96cbd7092bc8495429 Mon Sep 17 00:00:00 2001 From: SDKAuto Date: Tue, 8 Apr 2025 10:11:31 +0000 Subject: [PATCH] CodeGen from PR 33698 in Azure/azure-rest-api-specs Merge 0426bf3308b9582c418b145b910798e0a53050cc into abb839b726184aa10f8d1eaac8e9fe590833619c --- .../azure-communication-messages/MANIFEST.in | 2 +- .../azure-communication-messages/_meta.json | 6 + .../apiview-properties.json | 60 +++ .../communication/messages/_api_versions.py | 17 - .../azure/communication/messages/_client.py | 10 +- .../communication/messages/_configuration.py | 10 +- .../communication/messages/_model_base.py | 65 ++- .../messages/_operations/_operations.py | 2 +- .../messages/_operations/_patch.py | 9 +- .../azure/communication/messages/_patch.py | 136 +----- .../communication/messages/_serialization.py | 178 ++------ .../messages/_shared/__init__.py | 5 - .../messages/_shared/auth_policy_utils.py | 52 --- .../communication/messages/_shared/models.py | 417 ------------------ .../communication/messages/_shared/policy.py | 120 ----- .../messages/_shared/user_credential.py | 143 ------ .../messages/_shared/user_credential_async.py | 148 ------- .../communication/messages/_shared/utils.py | 89 ---- .../messages/_shared/utils_async.py | 30 -- .../azure/communication/messages/_types.py | 12 - .../azure/communication/messages/_version.py | 2 +- .../communication/messages/aio/_client.py | 10 +- .../messages/aio/_configuration.py | 10 +- .../messages/aio/_operations/_operations.py | 3 +- .../messages/aio/_operations/_patch.py | 9 +- .../communication/messages/aio/_patch.py | 143 +----- .../communication/messages/models/_enums.py | 4 +- .../communication/messages/models/_models.py | 344 ++++++--------- .../communication/messages/models/_patch.py | 9 +- .../generated_samples/stream_get_media.py | 33 ++ .../generated_tests/conftest.py | 58 +++ .../generated_tests/test_message_template.py | 24 + .../test_message_template_async.py | 25 ++ .../test_notification_messages.py | 35 ++ .../test_notification_messages_async.py | 36 ++ .../generated_tests/testpreparer.py | 44 ++ .../generated_tests/testpreparer_async.py | 31 ++ .../samples/download_media.py | 1 + .../samples/get_templates_list.py | 1 + .../samples/get_templates_list_async.py | 1 + .../send_audio_notification_messages.py | 1 + .../send_document_notification_messages.py | 1 + .../send_image_notification_messages.py | 1 + .../send_image_notification_messages_async.py | 1 + .../send_reaction_notification_messages.py | 1 + .../send_sticker_notification_messages.py | 1 + .../send_template_notification_messages.py | 1 + ...nd_template_notification_messages_async.py | 1 + .../send_text_notification_messages.py | 1 + .../send_text_notification_messages_async.py | 1 + ...ication_messages_with_token_credentials.py | 1 + .../send_video_notification_messages.py | 1 + ...end_whatsapp_list_notification_messages.py | 1 + ...whatsapp_urlbased_notification_messages.py | 1 + ...atsappreplybutton_notification_messages.py | 1 + .../azure-communication-messages/setup.py | 4 +- .../_shared/communication_service_preparer.py | 1 + .../tsp-location.yaml | 4 +- 58 files changed, 686 insertions(+), 1672 deletions(-) create mode 100644 sdk/communication/azure-communication-messages/_meta.json create mode 100644 sdk/communication/azure-communication-messages/apiview-properties.json delete mode 100644 sdk/communication/azure-communication-messages/azure/communication/messages/_api_versions.py delete mode 100644 sdk/communication/azure-communication-messages/azure/communication/messages/_shared/__init__.py delete mode 100644 sdk/communication/azure-communication-messages/azure/communication/messages/_shared/auth_policy_utils.py delete mode 100644 sdk/communication/azure-communication-messages/azure/communication/messages/_shared/models.py delete mode 100644 sdk/communication/azure-communication-messages/azure/communication/messages/_shared/policy.py delete mode 100644 sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential.py delete mode 100644 sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential_async.py delete mode 100644 sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils.py delete mode 100644 sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils_async.py delete mode 100644 sdk/communication/azure-communication-messages/azure/communication/messages/_types.py create mode 100644 sdk/communication/azure-communication-messages/generated_samples/stream_get_media.py create mode 100644 sdk/communication/azure-communication-messages/generated_tests/conftest.py create mode 100644 sdk/communication/azure-communication-messages/generated_tests/test_message_template.py create mode 100644 sdk/communication/azure-communication-messages/generated_tests/test_message_template_async.py create mode 100644 sdk/communication/azure-communication-messages/generated_tests/test_notification_messages.py create mode 100644 sdk/communication/azure-communication-messages/generated_tests/test_notification_messages_async.py create mode 100644 sdk/communication/azure-communication-messages/generated_tests/testpreparer.py create mode 100644 sdk/communication/azure-communication-messages/generated_tests/testpreparer_async.py diff --git a/sdk/communication/azure-communication-messages/MANIFEST.in b/sdk/communication/azure-communication-messages/MANIFEST.in index 0808b8a6a118..ba2a01329f05 100644 --- a/sdk/communication/azure-communication-messages/MANIFEST.in +++ b/sdk/communication/azure-communication-messages/MANIFEST.in @@ -4,4 +4,4 @@ include azure/communication/messages/py.typed recursive-include tests *.py recursive-include samples *.py *.md include azure/__init__.py -include azure/communication/__init__.py \ No newline at end of file +include azure/communication/__init__.py diff --git a/sdk/communication/azure-communication-messages/_meta.json b/sdk/communication/azure-communication-messages/_meta.json new file mode 100644 index 000000000000..27a85453f4da --- /dev/null +++ b/sdk/communication/azure-communication-messages/_meta.json @@ -0,0 +1,6 @@ +{ + "commit": "5b8b9e16f73291ccad4972febd28ca32ff908cd1", + "repository_url": "https://github.com/Azure/azure-rest-api-specs", + "typespec_src": "specification/communication/Communication.Messages", + "@azure-tools/typespec-python": "0.42.2" +} \ No newline at end of file diff --git a/sdk/communication/azure-communication-messages/apiview-properties.json b/sdk/communication/azure-communication-messages/apiview-properties.json new file mode 100644 index 000000000000..7873798bec9d --- /dev/null +++ b/sdk/communication/azure-communication-messages/apiview-properties.json @@ -0,0 +1,60 @@ +{ + "CrossLanguagePackageId": "Azure.Communication.MessagesService", + "CrossLanguageDefinitionId": { + "azure.communication.messages.models.ActionBindings": "Azure.Communication.MessagesService.ActionBindings", + "azure.communication.messages.models.ActionGroup": "Azure.Communication.MessagesService.ActionGroup", + "azure.communication.messages.models.MessageContent": "Azure.Communication.MessagesService.MessageContent", + "azure.communication.messages.models.ActionGroupContent": "Azure.Communication.MessagesService.ActionGroupContent", + "azure.communication.messages.models.ActionGroupItem": "Azure.Communication.MessagesService.ActionGroupItem", + "azure.communication.messages.models.NotificationContent": "Azure.Communication.MessagesService.NotificationContent", + "azure.communication.messages.models.AudioNotificationContent": "Azure.Communication.MessagesService.AudioNotificationContent", + "azure.communication.messages.models.ButtonContent": "Azure.Communication.MessagesService.ButtonContent", + "azure.communication.messages.models.ButtonSetContent": "Azure.Communication.MessagesService.ButtonSetContent", + "azure.communication.messages.models.DocumentMessageContent": "Azure.Communication.MessagesService.DocumentMessageContent", + "azure.communication.messages.models.DocumentNotificationContent": "Azure.Communication.MessagesService.DocumentNotificationContent", + "azure.communication.messages.models.ImageMessageContent": "Azure.Communication.MessagesService.ImageMessageContent", + "azure.communication.messages.models.ImageNotificationContent": "Azure.Communication.MessagesService.ImageNotificationContent", + "azure.communication.messages.models.InteractiveMessage": "Azure.Communication.MessagesService.InteractiveMessage", + "azure.communication.messages.models.InteractiveNotificationContent": "Azure.Communication.MessagesService.InteractiveNotificationContent", + "azure.communication.messages.models.LinkContent": "Azure.Communication.MessagesService.LinkContent", + "azure.communication.messages.models.MediaNotificationContent": "Azure.Communication.MessagesService.MediaNotificationContent", + "azure.communication.messages.models.MessageReceipt": "Azure.Communication.MessagesService.MessageReceipt", + "azure.communication.messages.models.MessageTemplate": "Azure.Communication.MessagesService.MessageTemplate", + "azure.communication.messages.models.MessageTemplateBindings": "Azure.Communication.MessagesService.MessageTemplateBindings", + "azure.communication.messages.models.MessageTemplateValue": "Azure.Communication.MessagesService.MessageTemplateValue", + "azure.communication.messages.models.MessageTemplateDocument": "Azure.Communication.MessagesService.MessageTemplateDocument", + "azure.communication.messages.models.MessageTemplateImage": "Azure.Communication.MessagesService.MessageTemplateImage", + "azure.communication.messages.models.MessageTemplateItem": "Azure.Communication.MessagesService.MessageTemplateItem", + "azure.communication.messages.models.MessageTemplateLocation": "Azure.Communication.MessagesService.MessageTemplateLocation", + "azure.communication.messages.models.MessageTemplateQuickAction": "Azure.Communication.MessagesService.MessageTemplateQuickAction", + "azure.communication.messages.models.MessageTemplateText": "Azure.Communication.MessagesService.MessageTemplateText", + "azure.communication.messages.models.MessageTemplateVideo": "Azure.Communication.MessagesService.MessageTemplateVideo", + "azure.communication.messages.models.ReactionNotificationContent": "Azure.Communication.MessagesService.ReactionNotificationContent", + "azure.communication.messages.models.SendMessageResult": "Azure.Communication.MessagesService.SendMessageResult", + "azure.communication.messages.models.StickerNotificationContent": "Azure.Communication.MessagesService.StickerNotificationContent", + "azure.communication.messages.models.TemplateNotificationContent": "Azure.Communication.MessagesService.TemplateNotificationContent", + "azure.communication.messages.models.TextMessageContent": "Azure.Communication.MessagesService.TextMessageContent", + "azure.communication.messages.models.TextNotificationContent": "Azure.Communication.MessagesService.TextNotificationContent", + "azure.communication.messages.models.VideoMessageContent": "Azure.Communication.MessagesService.VideoMessageContent", + "azure.communication.messages.models.VideoNotificationContent": "Azure.Communication.MessagesService.VideoNotificationContent", + "azure.communication.messages.models.WhatsAppButtonActionBindings": "Azure.Communication.MessagesService.WhatsAppButtonActionBindings", + "azure.communication.messages.models.WhatsAppListActionBindings": "Azure.Communication.MessagesService.WhatsAppListActionBindings", + "azure.communication.messages.models.WhatsAppMessageTemplateBindings": "Azure.Communication.MessagesService.WhatsAppMessageTemplateBindings", + "azure.communication.messages.models.WhatsAppMessageTemplateBindingsButton": "Azure.Communication.MessagesService.WhatsAppMessageTemplateBindingsButton", + "azure.communication.messages.models.WhatsAppMessageTemplateBindingsComponent": "Azure.Communication.MessagesService.WhatsAppMessageTemplateBindingsComponent", + "azure.communication.messages.models.WhatsAppMessageTemplateItem": "Azure.Communication.MessagesService.WhatsAppMessageTemplateItem", + "azure.communication.messages.models.WhatsAppUrlActionBindings": "Azure.Communication.MessagesService.WhatsAppUrlActionBindings", + "azure.communication.messages.models.RepeatabilityResult": "Azure.Core.RepeatabilityResult", + "azure.communication.messages.models.CommunicationMessageKind": "Azure.Communication.MessagesService.CommunicationMessageKind", + "azure.communication.messages.models.MessageContentKind": "Azure.Communication.MessagesService.MessageContentKind", + "azure.communication.messages.models.MessageActionBindingKind": "Azure.Communication.MessagesService.MessageActionBindingKind", + "azure.communication.messages.models.MessageTemplateValueKind": "Azure.Communication.MessagesService.MessageTemplateValueKind", + "azure.communication.messages.models.MessageTemplateBindingsKind": "Azure.Communication.MessagesService.MessageTemplateBindingsKind", + "azure.communication.messages.models.WhatsAppMessageButtonSubType": "Azure.Communication.MessagesService.WhatsAppMessageButtonSubType", + "azure.communication.messages.models.MessageTemplateStatus": "Azure.Communication.MessagesService.MessageTemplateStatus", + "azure.communication.messages.models.CommunicationMessagesChannel": "Azure.Communication.MessagesService.CommunicationMessagesChannel", + "azure.communication.messages.NotificationMessagesClient.send": "Azure.Communication.MessagesService.NotificationMessagesClient.send", + "azure.communication.messages.NotificationMessagesClient.download_media": "ClientForAcsMessages.NotificationMessagesClient.downloadMedia", + "azure.communication.messages.MessageTemplateClient.list_templates": "Azure.Communication.MessagesService.MessageTemplateClient.listTemplates" + } +} \ No newline at end of file diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_api_versions.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_api_versions.py deleted file mode 100644 index 98685e53479c..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_api_versions.py +++ /dev/null @@ -1,17 +0,0 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - -from enum import Enum -from azure.core import CaseInsensitiveEnumMeta - - -class ApiVersion(str, Enum, metaclass=CaseInsensitiveEnumMeta): - V2023_08_24_PREVIEW = "2023-08-24-preview" - V2024_02_01 = "2024-02-01" - V2024_08_30 = "2024-08-30" - V2025_01_15_PREVIEW = "2025-01-15-preview" - - -DEFAULT_VERSION = ApiVersion.V2025_01_15_preview.value diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_client.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_client.py index a32a72ef112a..b4d1a2ef062b 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_client.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_client.py @@ -27,10 +27,11 @@ class NotificationMessagesClient(NotificationMessagesClientOperationsMixin): """NotificationMessagesClient. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials.TokenCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is @@ -106,10 +107,11 @@ class MessageTemplateClient(MessageTemplateClientOperationsMixin): """MessageTemplateClient. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials.TokenCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_configuration.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_configuration.py index b573ba282c5a..2a72ab832af5 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_configuration.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_configuration.py @@ -24,10 +24,11 @@ class NotificationMessagesClientConfiguration: # pylint: disable=too-many-insta attributes. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials.TokenCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is @@ -80,10 +81,11 @@ class MessageTemplateClientConfiguration: # pylint: disable=too-many-instance-a attributes. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials.TokenCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_model_base.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_model_base.py index 7f73b97b23ef..065b17f67c46 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_model_base.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_model_base.py @@ -2,8 +2,9 @@ # coding=utf-8 # -------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- # pylint: disable=protected-access, broad-except @@ -373,15 +374,34 @@ def __ne__(self, other: typing.Any) -> bool: return not self.__eq__(other) def keys(self) -> typing.KeysView[str]: + """ + :returns: a set-like object providing a view on D's keys + :rtype: ~typing.KeysView + """ return self._data.keys() def values(self) -> typing.ValuesView[typing.Any]: + """ + :returns: an object providing a view on D's values + :rtype: ~typing.ValuesView + """ return self._data.values() def items(self) -> typing.ItemsView[str, typing.Any]: + """ + :returns: set-like object providing a view on D's items + :rtype: ~typing.ItemsView + """ return self._data.items() def get(self, key: str, default: typing.Any = None) -> typing.Any: + """ + Get the value for key if key is in the dictionary, else default. + :param str key: The key to look up. + :param any default: The value to return if key is not in the dictionary. Defaults to None + :returns: D[k] if k in D, else d. + :rtype: any + """ try: return self[key] except KeyError: @@ -397,17 +417,38 @@ def pop(self, key: str, default: _T) -> _T: ... def pop(self, key: str, default: typing.Any) -> typing.Any: ... def pop(self, key: str, default: typing.Any = _UNSET) -> typing.Any: + """ + Removes specified key and return the corresponding value. + :param str key: The key to pop. + :param any default: The value to return if key is not in the dictionary + :returns: The value corresponding to the key. + :rtype: any + :raises KeyError: If key is not found and default is not given. + """ if default is _UNSET: return self._data.pop(key) return self._data.pop(key, default) def popitem(self) -> typing.Tuple[str, typing.Any]: + """ + Removes and returns some (key, value) pair + :returns: The (key, value) pair. + :rtype: tuple + :raises KeyError: if D is empty. + """ return self._data.popitem() def clear(self) -> None: + """ + Remove all items from D. + """ self._data.clear() def update(self, *args: typing.Any, **kwargs: typing.Any) -> None: + """ + Updates D from mapping/iterable E and F. + :param any args: Either a mapping object or an iterable of key-value pairs. + """ self._data.update(*args, **kwargs) @typing.overload @@ -417,6 +458,13 @@ def setdefault(self, key: str, default: None = None) -> None: ... def setdefault(self, key: str, default: typing.Any) -> typing.Any: ... def setdefault(self, key: str, default: typing.Any = _UNSET) -> typing.Any: + """ + Same as calling D.get(k, d), and setting D[k]=d if k not found + :param str key: The key to look up. + :param any default: The value to set if key is not in the dictionary + :returns: D[k] if k in D, else d. + :rtype: any + """ if default is _UNSET: return self._data.setdefault(key) return self._data.setdefault(key, default) @@ -910,6 +958,19 @@ def _failsafe_deserialize( return None +def _failsafe_deserialize_xml( + deserializer: typing.Any, + value: typing.Any, +) -> typing.Any: + try: + return _deserialize_xml(deserializer, value) + except DeserializationError: + _LOGGER.warning( + "Ran into a deserialization error. Ignoring since this is failsafe deserialization", exc_info=True + ) + return None + + class _RestField: def __init__( self, diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_operations.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_operations.py index b5eedc436115..867d8ebb233e 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_operations.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_operations.py @@ -387,7 +387,7 @@ def prepare_request(next_link=None): def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize(List[_models.MessageTemplateItem], deserialized["value"]) + list_of_elem = _deserialize(List[_models.MessageTemplateItem], deserialized.get("value", [])) if cls: list_of_elem = cls(list_of_elem) # type: ignore return deserialized.get("nextLink") or None, iter(list_of_elem) diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_patch.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_patch.py index f7dd32510333..8bcb627aa475 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_patch.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_patch.py @@ -1,7 +1,8 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------- """Customize generated code here. Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_patch.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_patch.py index eb3162ba82cb..8bcb627aa475 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_patch.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_patch.py @@ -1,137 +1,15 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------- """Customize generated code here. Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ -from typing import List, Any, Union -from urllib.parse import urlparse -from azure.core.credentials import TokenCredential, AzureKeyCredential -from ._shared.utils import parse_connection_str -from ._client import ( - NotificationMessagesClient as NotificationMessagesClientGenerated, - MessageTemplateClient as MessageTemplateClientGenerated, -) -from ._shared.auth_policy_utils import get_authentication_policy -from ._api_versions import DEFAULT_VERSION +from typing import List - -class NotificationMessagesClient(NotificationMessagesClientGenerated): - """A client to interact with the AzureCommunicationService Messaging service. - - This client provides operations to create and update jobs, policies and workers. - - :param str endpoint: - The endpoint of the Azure Communication resource. - :param Union[TokenCredential, AsyncTokenCredential] credential: - The credentials with which to authenticate - - :keyword api_version: Azure Communication Messaging API version. - Default value is "2023-11-01". - Note that overriding this default value may result in unsupported behavior. - """ - - def __init__(self, endpoint: str, credential: Union[TokenCredential, AzureKeyCredential], **kwargs: Any) -> None: - if not credential: - raise ValueError("credential can not be None") - - try: - if not endpoint.lower().startswith("http"): - endpoint = "https://" + endpoint - except AttributeError: - raise ValueError("Host URL must be a string") # pylint:disable=raise-missing-from - - parsed_url = urlparse(endpoint.rstrip("/")) - if not parsed_url.netloc: - raise ValueError("Invalid URL: {}".format(endpoint)) - - self._endpoint = endpoint - self._api_version = kwargs.pop("api_version", DEFAULT_VERSION) - self._authentication_policy = get_authentication_policy(endpoint, credential) - self._credential = credential - super().__init__( - self._endpoint, - self._credential, - authentication_policy=self._authentication_policy, - api_version=self._api_version, - **kwargs - ) - - @classmethod - def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "NotificationMessagesClient": - """Create NotificationMessagesClient from a Connection String. - - :param conn_str: Azure communication service connection string. Required. - :type conn_str: str - :return: instance of NotificationMessagesClient - :rtype: - ~azure.communication.messages.NotificationMessagesClient - """ - endpoint, access_key = parse_connection_str(conn_str) - return cls(endpoint, AzureKeyCredential(access_key), **kwargs) - - -class MessageTemplateClient(MessageTemplateClientGenerated): - """A client to interact with the AzureCommunicationService Messaging service. - - This client provides Advanced Messaging. - - :param str endpoint: - The endpoint of the Azure Communication resource. - :param Union[TokenCredential, AsyncTokenCredential] credential: - The credentials with which to authenticate - - :keyword api_version: Azure Communication Messages API version. Default value is "2024-02-01". - Note that overriding this default value may result in unsupported behavior. - :paramtype api_version: str - """ - - def __init__(self, endpoint: str, credential: Union[TokenCredential, AzureKeyCredential], **kwargs: Any) -> "None": - if not credential: - raise ValueError("credential can not be None") - - try: - if not endpoint.lower().startswith("http"): - endpoint = "https://" + endpoint - except AttributeError: - raise ValueError("Host URL must be a string") # pylint: disable=raise-missing-from - - parsed_url = urlparse(endpoint.rstrip("/")) - if not parsed_url.netloc: - raise ValueError("Invalid URL: {}".format(endpoint)) - - self._endpoint = endpoint - self._api_version = kwargs.pop("api_version", DEFAULT_VERSION) - self._authentication_policy = get_authentication_policy(endpoint, credential) - self._credential = credential - super().__init__( - self._endpoint, - self._credential, - authentication_policy=self._authentication_policy, - api_version=self._api_version, - **kwargs - ) - - @classmethod - def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "MessageTemplateClient": - """Create MessageTemplateClient from a Connection String. - - :param conn_str: Azure communication service connection string. Required. - :type conn_str: str - :return: instance of MessageTemplateClient - :rtype: - ~azure.communication.messages.MessageTemplateClient - """ - endpoint, access_key = parse_connection_str(conn_str) - return cls(endpoint, AzureKeyCredential(access_key), **kwargs) - - -__all__: List[str] = [ - "NotificationMessagesClient", - "MessageTemplateClient", -] # Add all objects you want publicly available to users at this package level +__all__: List[str] = [] # Add all objects you want publicly available to users at this package level def patch_sdk(): diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_serialization.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_serialization.py index b24ab2885450..eb86ea23c965 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_serialization.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_serialization.py @@ -1,28 +1,10 @@ -# pylint: disable=too-many-lines +# pylint: disable=line-too-long,useless-suppression,too-many-lines +# coding=utf-8 # -------------------------------------------------------------------------- -# # Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- # pyright: reportUnnecessaryTypeIgnoreComment=false @@ -48,9 +30,7 @@ IO, Mapping, Callable, - TypeVar, MutableMapping, - Type, List, ) @@ -61,13 +41,13 @@ import xml.etree.ElementTree as ET import isodate # type: ignore +from typing_extensions import Self from azure.core.exceptions import DeserializationError, SerializationError from azure.core.serialization import NULL as CoreNull _BOM = codecs.BOM_UTF8.decode(encoding="utf-8") -ModelType = TypeVar("ModelType", bound="Model") JSON = MutableMapping[str, Any] @@ -185,73 +165,7 @@ def deserialize_from_http_generics(cls, body_bytes: Optional[Union[AnyStr, IO]], except NameError: _long_type = int - -class UTC(datetime.tzinfo): - """Time Zone info for handling UTC""" - - def utcoffset(self, dt): - """UTF offset for UTC is 0. - - :param datetime.datetime dt: The datetime - :returns: The offset - :rtype: datetime.timedelta - """ - return datetime.timedelta(0) - - def tzname(self, dt): - """Timestamp representation. - - :param datetime.datetime dt: The datetime - :returns: The timestamp representation - :rtype: str - """ - return "Z" - - def dst(self, dt): - """No daylight saving for UTC. - - :param datetime.datetime dt: The datetime - :returns: The daylight saving time - :rtype: datetime.timedelta - """ - return datetime.timedelta(hours=1) - - -try: - from datetime import timezone as _FixedOffset # type: ignore -except ImportError: # Python 2.7 - - class _FixedOffset(datetime.tzinfo): # type: ignore - """Fixed offset in minutes east from UTC. - Copy/pasted from Python doc - :param datetime.timedelta offset: offset in timedelta format - """ - - def __init__(self, offset) -> None: - self.__offset = offset - - def utcoffset(self, dt): - return self.__offset - - def tzname(self, dt): - return str(self.__offset.total_seconds() / 3600) - - def __repr__(self): - return "".format(self.tzname(None)) - - def dst(self, dt): - return datetime.timedelta(0) - - def __getinitargs__(self): - return (self.__offset,) - - -try: - from datetime import timezone - - TZ_UTC = timezone.utc -except ImportError: - TZ_UTC = UTC() # type: ignore +TZ_UTC = datetime.timezone.utc _FLATTEN = re.compile(r"(? ModelType: + def deserialize(cls, data: Any, content_type: Optional[str] = None) -> Self: """Parse a str using the RestAPI syntax and return a model. :param str data: A str using RestAPI structure. JSON by default. :param str content_type: JSON by default, set application/xml if XML. :returns: An instance of this model - :raises: DeserializationError if something went wrong - :rtype: ModelType + :raises DeserializationError: if something went wrong + :rtype: Self """ deserializer = Deserializer(cls._infer_class_models()) return deserializer(cls.__name__, data, content_type=content_type) # type: ignore @classmethod def from_dict( - cls: Type[ModelType], + cls, data: Any, key_extractors: Optional[Callable[[str, Dict[str, Any], Any], Any]] = None, content_type: Optional[str] = None, - ) -> ModelType: + ) -> Self: """Parse a dict using given key extractor return a model. By default consider key @@ -479,8 +393,8 @@ def from_dict( :param function key_extractors: A key extractor function. :param str content_type: JSON by default, set application/xml if XML. :returns: An instance of this model - :raises: DeserializationError if something went wrong - :rtype: ModelType + :raises DeserializationError: if something went wrong + :rtype: Self """ deserializer = Deserializer(cls._infer_class_models()) deserializer.key_extractors = ( # type: ignore @@ -626,7 +540,7 @@ def _serialize( # pylint: disable=too-many-nested-blocks, too-many-branches, to :param object target_obj: The data to be serialized. :param str data_type: The type to be serialized from. :rtype: str, dict - :raises: SerializationError if serialization fails. + :raises SerializationError: if serialization fails. :returns: The serialized data. """ key_transformer = kwargs.get("key_transformer", self.key_transformer) @@ -736,8 +650,8 @@ def body(self, data, data_type, **kwargs): :param object data: The data to be serialized. :param str data_type: The type to be serialized from. :rtype: dict - :raises: SerializationError if serialization fails. - :raises: ValueError if data is None + :raises SerializationError: if serialization fails. + :raises ValueError: if data is None :returns: The serialized request body """ @@ -781,8 +695,8 @@ def url(self, name, data, data_type, **kwargs): :param str data_type: The type to be serialized from. :rtype: str :returns: The serialized URL path - :raises: TypeError if serialization fails. - :raises: ValueError if data is None + :raises TypeError: if serialization fails. + :raises ValueError: if data is None """ try: output = self.serialize_data(data, data_type, **kwargs) @@ -805,8 +719,8 @@ def query(self, name, data, data_type, **kwargs): :param object data: The data to be serialized. :param str data_type: The type to be serialized from. :rtype: str, list - :raises: TypeError if serialization fails. - :raises: ValueError if data is None + :raises TypeError: if serialization fails. + :raises ValueError: if data is None :returns: The serialized query parameter """ try: @@ -835,8 +749,8 @@ def header(self, name, data, data_type, **kwargs): :param object data: The data to be serialized. :param str data_type: The type to be serialized from. :rtype: str - :raises: TypeError if serialization fails. - :raises: ValueError if data is None + :raises TypeError: if serialization fails. + :raises ValueError: if data is None :returns: The serialized header """ try: @@ -855,9 +769,9 @@ def serialize_data(self, data, data_type, **kwargs): :param object data: The data to be serialized. :param str data_type: The type to be serialized from. - :raises: AttributeError if required data is None. - :raises: ValueError if data is None - :raises: SerializationError if serialization fails. + :raises AttributeError: if required data is None. + :raises ValueError: if data is None + :raises SerializationError: if serialization fails. :returns: The serialized data. :rtype: str, int, float, bool, dict, list """ @@ -1192,7 +1106,7 @@ def serialize_rfc(attr, **kwargs): # pylint: disable=unused-argument :param Datetime attr: Object to be serialized. :rtype: str - :raises: TypeError if format invalid. + :raises TypeError: if format invalid. :return: serialized rfc """ try: @@ -1218,7 +1132,7 @@ def serialize_iso(attr, **kwargs): # pylint: disable=unused-argument :param Datetime attr: Object to be serialized. :rtype: str - :raises: SerializationError if format invalid. + :raises SerializationError: if format invalid. :return: serialized iso """ if isinstance(attr, str): @@ -1251,7 +1165,7 @@ def serialize_unix(attr, **kwargs): # pylint: disable=unused-argument :param Datetime attr: Object to be serialized. :rtype: int - :raises: SerializationError if format invalid + :raises SerializationError: if format invalid :return: serialied unix """ if isinstance(attr, int): @@ -1429,7 +1343,7 @@ def xml_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument # Iter and wrapped, should have found one node only (the wrap one) if len(children) != 1: raise DeserializationError( - "Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format( # pylint: disable=line-too-long + "Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format( xml_name ) ) @@ -1488,7 +1402,7 @@ def __call__(self, target_obj, response_data, content_type=None): :param str target_obj: Target data type to deserialize to. :param requests.Response response_data: REST response object. :param str content_type: Swagger "produces" if available. - :raises: DeserializationError if deserialization fails. + :raises DeserializationError: if deserialization fails. :return: Deserialized object. :rtype: object """ @@ -1502,7 +1416,7 @@ def _deserialize(self, target_obj, data): # pylint: disable=inconsistent-return :param str target_obj: Target data type to deserialize to. :param object data: Object to deserialize. - :raises: DeserializationError if deserialization fails. + :raises DeserializationError: if deserialization fails. :return: Deserialized object. :rtype: object """ @@ -1717,7 +1631,7 @@ def deserialize_data(self, data, data_type): # pylint: disable=too-many-return- :param str data: The response string to be deserialized. :param str data_type: The type to deserialize to. - :raises: DeserializationError if deserialization fails. + :raises DeserializationError: if deserialization fails. :return: Deserialized object. :rtype: object """ @@ -1799,7 +1713,7 @@ def deserialize_object(self, attr, **kwargs): # pylint: disable=too-many-return :param dict attr: Dictionary to be deserialized. :return: Deserialized object. :rtype: dict - :raises: TypeError if non-builtin datatype encountered. + :raises TypeError: if non-builtin datatype encountered. """ if attr is None: return None @@ -1845,7 +1759,7 @@ def deserialize_basic(self, attr, data_type): # pylint: disable=too-many-return :param str data_type: deserialization data type. :return: Deserialized basic type. :rtype: str, int, float or bool - :raises: TypeError if string format is not valid. + :raises TypeError: if string format is not valid. """ # If we're here, data is supposed to be a basic type. # If it's still an XML node, take the text @@ -1936,7 +1850,7 @@ def deserialize_bytearray(attr): :param str attr: response string to be deserialized. :return: Deserialized bytearray :rtype: bytearray - :raises: TypeError if string format invalid. + :raises TypeError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -1949,7 +1863,7 @@ def deserialize_base64(attr): :param str attr: response string to be deserialized. :return: Deserialized base64 string :rtype: bytearray - :raises: TypeError if string format invalid. + :raises TypeError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -1964,7 +1878,7 @@ def deserialize_decimal(attr): :param str attr: response string to be deserialized. :return: Deserialized decimal - :raises: DeserializationError if string format invalid. + :raises DeserializationError: if string format invalid. :rtype: decimal """ if isinstance(attr, ET.Element): @@ -1982,7 +1896,7 @@ def deserialize_long(attr): :param str attr: response string to be deserialized. :return: Deserialized int :rtype: long or int - :raises: ValueError if string format invalid. + :raises ValueError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -1995,7 +1909,7 @@ def deserialize_duration(attr): :param str attr: response string to be deserialized. :return: Deserialized duration :rtype: TimeDelta - :raises: DeserializationError if string format invalid. + :raises DeserializationError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -2013,7 +1927,7 @@ def deserialize_date(attr): :param str attr: response string to be deserialized. :return: Deserialized date :rtype: Date - :raises: DeserializationError if string format invalid. + :raises DeserializationError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -2029,7 +1943,7 @@ def deserialize_time(attr): :param str attr: response string to be deserialized. :return: Deserialized time :rtype: datetime.time - :raises: DeserializationError if string format invalid. + :raises DeserializationError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -2044,14 +1958,14 @@ def deserialize_rfc(attr): :param str attr: response string to be deserialized. :return: Deserialized RFC datetime :rtype: Datetime - :raises: DeserializationError if string format invalid. + :raises DeserializationError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text try: parsed_date = email.utils.parsedate_tz(attr) # type: ignore date_obj = datetime.datetime( - *parsed_date[:6], tzinfo=_FixedOffset(datetime.timedelta(minutes=(parsed_date[9] or 0) / 60)) + *parsed_date[:6], tzinfo=datetime.timezone(datetime.timedelta(minutes=(parsed_date[9] or 0) / 60)) ) if not date_obj.tzinfo: date_obj = date_obj.astimezone(tz=TZ_UTC) @@ -2067,7 +1981,7 @@ def deserialize_iso(attr): :param str attr: response string to be deserialized. :return: Deserialized ISO datetime :rtype: Datetime - :raises: DeserializationError if string format invalid. + :raises DeserializationError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -2105,7 +2019,7 @@ def deserialize_unix(attr): :param int attr: Object to be serialized. :return: Deserialized datetime :rtype: Datetime - :raises: DeserializationError if format invalid + :raises DeserializationError: if format invalid """ if isinstance(attr, ET.Element): attr = int(attr.text) # type: ignore diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/__init__.py deleted file mode 100644 index 5b396cd202e8..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# -------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/auth_policy_utils.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/auth_policy_utils.py deleted file mode 100644 index e0bdebfcc294..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/auth_policy_utils.py +++ /dev/null @@ -1,52 +0,0 @@ -# ------------------------------------------------------------------------ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# ------------------------------------------------------------------------- - -from typing import Union -from azure.core.credentials import TokenCredential, AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.policies import ( - AsyncBearerTokenCredentialPolicy, - BearerTokenCredentialPolicy, -) -from .._shared.policy import HMACCredentialsPolicy - - -def get_authentication_policy( - endpoint: str, - credential: Union[TokenCredential, AsyncTokenCredential, AzureKeyCredential, str], - decode_url: bool = False, - is_async: bool = False, -) -> Union[AsyncBearerTokenCredentialPolicy, BearerTokenCredentialPolicy, HMACCredentialsPolicy]: - """Returns the correct authentication policy based on which credential is being passed. - - :param endpoint: The endpoint to which we are authenticating to. - :type endpoint: str - :param credential: The credential we use to authenticate to the service - :type credential: Union[TokenCredential, AsyncTokenCredential, AzureKeyCredential, str] - :param bool decode_url: `True` if there is a need to decode the url. Default value is `False` - :param bool is_async: For async clients there is a need to decode the url - - :return: Either AsyncBearerTokenCredentialPolicy or BearerTokenCredentialPolicy or HMACCredentialsPolicy - :rtype: ~azure.core.pipeline.policies.AsyncBearerTokenCredentialPolicy or - ~azure.core.pipeline.policies.BearerTokenCredentialPolicy or - ~azure.communication.messages.shared.policy.HMACCredentialsPolicy - """ - - if credential is None: - raise ValueError("Parameter 'credential' must not be None.") - if hasattr(credential, "get_token"): - if is_async: - return AsyncBearerTokenCredentialPolicy( - credential, "https://communication.azure.com//.default" # type: ignore - ) - return BearerTokenCredentialPolicy(credential, "https://communication.azure.com//.default") # type: ignore - if isinstance(credential, (AzureKeyCredential, str)): - return HMACCredentialsPolicy(endpoint, credential, decode_url=decode_url) - - raise TypeError( - f"Unsupported credential: {format(type(credential))}. Use an access token string to use HMACCredentialsPolicy" - "or a token credential from azure.identity" - ) diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/models.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/models.py deleted file mode 100644 index 43875e1197e5..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/models.py +++ /dev/null @@ -1,417 +0,0 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ -from enum import Enum -import warnings -from typing import Mapping, Optional, Union, Any, cast -from typing_extensions import Literal, TypedDict, Protocol, runtime_checkable - -from azure.core import CaseInsensitiveEnumMeta - - -class DeprecatedEnumMeta(CaseInsensitiveEnumMeta): - - def __getattribute__(cls, item): - if item.upper() == "MICROSOFT_BOT": - warnings.warn( - "MICROSOFT_BOT is deprecated and has been replaced by \ - MICROSOFT_TEAMS_APP identifier.", - DeprecationWarning, - ) - item = "MICROSOFT_TEAMS_APP" - return super().__getattribute__(item) - - -class CommunicationIdentifierKind(str, Enum, metaclass=DeprecatedEnumMeta): - """Communication Identifier Kind. - - For checking yet unknown identifiers it is better to rely on the presence of the `raw_id` property, - as new or existing distinct type identifiers always contain the `raw_id` property. - It is not advisable to rely on the `kind` property with a value `unknown`, - as it could become a new or existing distinct type in the future. - """ - - UNKNOWN = "unknown" - COMMUNICATION_USER = "communication_user" - PHONE_NUMBER = "phone_number" - MICROSOFT_TEAMS_USER = "microsoft_teams_user" - MICROSOFT_TEAMS_APP = "microsoft_teams_app" - - -class CommunicationCloudEnvironment(str, Enum, metaclass=CaseInsensitiveEnumMeta): - """The cloud environment that the identifier belongs to""" - - PUBLIC = "PUBLIC" - DOD = "DOD" - GCCH = "GCCH" - - -@runtime_checkable -class CommunicationIdentifier(Protocol): - """Communication Identifier.""" - - @property - def raw_id(self) -> str: - """The raw ID of the identifier.""" - ... - - @property - def kind(self) -> CommunicationIdentifierKind: - """The type of identifier.""" - ... - - @property - def properties(self) -> Mapping[str, Any]: - """The properties of the identifier.""" - ... - - -PHONE_NUMBER_PREFIX = "4:" -BOT_PREFIX = "28:" -BOT_PUBLIC_CLOUD_PREFIX = "28:orgid:" -BOT_DOD_CLOUD_PREFIX = "28:dod:" -BOT_DOD_CLOUD_GLOBAL_PREFIX = "28:dod-global:" -BOT_GCCH_CLOUD_PREFIX = "28:gcch:" -BOT_GCCH_CLOUD_GLOBAL_PREFIX = "28:gcch-global:" -TEAMS_APP_PUBLIC_CLOUD_PREFIX = "28:orgid:" -TEAMS_APP_DOD_CLOUD_PREFIX = "28:dod:" -TEAMS_APP_GCCH_CLOUD_PREFIX = "28:gcch:" -TEAMS_USER_ANONYMOUS_PREFIX = "8:teamsvisitor:" -TEAMS_USER_PUBLIC_CLOUD_PREFIX = "8:orgid:" -TEAMS_USER_DOD_CLOUD_PREFIX = "8:dod:" -TEAMS_USER_GCCH_CLOUD_PREFIX = "8:gcch:" -ACS_USER_PREFIX = "8:acs:" -ACS_USER_DOD_CLOUD_PREFIX = "8:dod-acs:" -ACS_USER_GCCH_CLOUD_PREFIX = "8:gcch-acs:" -SPOOL_USER_PREFIX = "8:spool:" - - -class CommunicationUserProperties(TypedDict): - """Dictionary of properties for a CommunicationUserIdentifier.""" - - id: str - """ID of the Communication user as returned from Azure Communication Identity.""" - - -class CommunicationUserIdentifier: - """Represents a user in Azure Communication Service.""" - - kind: Literal[CommunicationIdentifierKind.COMMUNICATION_USER] = CommunicationIdentifierKind.COMMUNICATION_USER - """The type of identifier.""" - properties: CommunicationUserProperties - """The properties of the identifier.""" - raw_id: str - """The raw ID of the identifier.""" - - def __init__(self, id: str, **kwargs: Any) -> None: - """ - :param str id: ID of the Communication user as returned from Azure Communication Identity. - :keyword str raw_id: The raw ID of the identifier. If not specified, the 'id' value will be used. - """ - self.properties = CommunicationUserProperties(id=id) - raw_id: Optional[str] = kwargs.get("raw_id") - self.raw_id = raw_id if raw_id is not None else id - - def __eq__(self, other): - try: - if other.raw_id: - return self.raw_id == other.raw_id - return self.raw_id == other.properties["id"] - except Exception: # pylint: disable=broad-except - return False - - -class PhoneNumberProperties(TypedDict): - """Dictionary of properties for a PhoneNumberIdentifier.""" - - value: str - """The phone number in E.164 format.""" - - -class PhoneNumberIdentifier: - """Represents a phone number.""" - - kind: Literal[CommunicationIdentifierKind.PHONE_NUMBER] = CommunicationIdentifierKind.PHONE_NUMBER - """The type of identifier.""" - properties: PhoneNumberProperties - """The properties of the identifier.""" - raw_id: str - """The raw ID of the identifier.""" - - def __init__(self, value: str, **kwargs: Any) -> None: - """ - :param str value: The phone number. - :keyword str raw_id: The raw ID of the identifier. If not specified, this will be constructed from - the 'value' parameter. - """ - self.properties = PhoneNumberProperties(value=value) - raw_id: Optional[str] = kwargs.get("raw_id") - self.raw_id = raw_id if raw_id is not None else self._format_raw_id(self.properties) - - def __eq__(self, other): - try: - if other.raw_id: - return self.raw_id == other.raw_id - return self.raw_id == self._format_raw_id(other.properties) - except Exception: # pylint:disable=broad-except - return False - - def _format_raw_id(self, properties: PhoneNumberProperties) -> str: - # We just assume correct E.164 format here because - # validation should only happen server-side, not client-side. - value = properties["value"] - return f"{PHONE_NUMBER_PREFIX}{value}" - - -class UnknownIdentifier: - """Represents an identifier of an unknown type. - - It will be encountered in communications with endpoints that are not - identifiable by this version of the SDK. - - For checking yet unknown identifiers it is better to rely on the presence of the `raw_id` property, - as new or existing distinct type identifiers always contain the `raw_id` property. - It is not advisable to rely on the `kind` property with a value `unknown`, - as it could become a new or existing distinct type in the future. - """ - - kind: Literal[CommunicationIdentifierKind.UNKNOWN] = CommunicationIdentifierKind.UNKNOWN - """The type of identifier.""" - properties: Mapping[str, Any] - """The properties of the identifier.""" - raw_id: str - """The raw ID of the identifier.""" - - def __init__(self, identifier: str) -> None: - """ - :param str identifier: The ID of the identifier. - """ - self.raw_id = identifier - self.properties = {} - - def __eq__(self, other): - try: - return self.raw_id == other.raw_id - except AttributeError: - return False - - -class MicrosoftTeamsUserProperties(TypedDict): - """Dictionary of properties for a MicrosoftTeamsUserIdentifier.""" - - user_id: str - """The id of the Microsoft Teams user. If the user isn't anonymous, the id is the AAD object id of the user.""" - is_anonymous: bool - """Set this to true if the user is anonymous for example when joining a meeting with a share link.""" - cloud: Union[CommunicationCloudEnvironment, str] - """Cloud environment that this identifier belongs to.""" - - -class MicrosoftTeamsUserIdentifier: - """Represents an identifier for a Microsoft Teams user.""" - - kind: Literal[CommunicationIdentifierKind.MICROSOFT_TEAMS_USER] = CommunicationIdentifierKind.MICROSOFT_TEAMS_USER - """The type of identifier.""" - properties: MicrosoftTeamsUserProperties - """The properties of the identifier.""" - raw_id: str - """The raw ID of the identifier.""" - - def __init__(self, user_id: str, **kwargs: Any) -> None: - """ - :param str user_id: Microsoft Teams user id. - :keyword bool is_anonymous: `True` if the identifier is anonymous. Default value is `False`. - :keyword cloud: Cloud environment that the user belongs to. Default value is `PUBLIC`. - :paramtype cloud: str or ~azure.communication.chat.CommunicationCloudEnvironment - :keyword str raw_id: The raw ID of the identifier. If not specified, this value will be constructed from - the other properties. - """ - self.properties = MicrosoftTeamsUserProperties( - user_id=user_id, - is_anonymous=kwargs.get("is_anonymous", False), - cloud=kwargs.get("cloud") or CommunicationCloudEnvironment.PUBLIC, - ) - raw_id: Optional[str] = kwargs.get("raw_id") - self.raw_id = raw_id if raw_id is not None else self._format_raw_id(self.properties) - - def __eq__(self, other): - try: - if other.raw_id: - return self.raw_id == other.raw_id - return self.raw_id == self._format_raw_id(other.properties) - except Exception: # pylint: disable=broad-except - return False - - def _format_raw_id(self, properties: MicrosoftTeamsUserProperties) -> str: - user_id = properties["user_id"] - if properties["is_anonymous"]: - return f"{TEAMS_USER_ANONYMOUS_PREFIX}{user_id}" - cloud = properties["cloud"] - if cloud == CommunicationCloudEnvironment.DOD: - return f"{TEAMS_USER_DOD_CLOUD_PREFIX}{user_id}" - if cloud == CommunicationCloudEnvironment.GCCH: - return f"{TEAMS_USER_GCCH_CLOUD_PREFIX}{user_id}" - if cloud == CommunicationCloudEnvironment.PUBLIC: - return f"{TEAMS_USER_PUBLIC_CLOUD_PREFIX}{user_id}" - return f"{TEAMS_USER_PUBLIC_CLOUD_PREFIX}{user_id}" - - -class MicrosoftTeamsAppProperties(TypedDict): - """Dictionary of properties for a MicrosoftTeamsAppIdentifier.""" - - app_id: str - """The id of the Microsoft Teams application.""" - cloud: Union[CommunicationCloudEnvironment, str] - """Cloud environment that this identifier belongs to.""" - - -class _botbackcompatdict(dict): - """Backwards compatible properties.""" - - def __getitem__(self, __key: Any) -> Any: - try: - return super().__getitem__(__key) - except KeyError: - if __key == "bot_id": - return super().__getitem__("app_id") - if __key == "is_resource_account_configured": - return True - raise - - -class MicrosoftTeamsAppIdentifier: - """Represents an identifier for a Microsoft Teams application.""" - - kind: Literal[CommunicationIdentifierKind.MICROSOFT_TEAMS_APP] = CommunicationIdentifierKind.MICROSOFT_TEAMS_APP - """The type of identifier.""" - properties: MicrosoftTeamsAppProperties - """The properties of the identifier.""" - raw_id: str - """The raw ID of the identifier.""" - - def __init__(self, app_id: str, **kwargs: Any) -> None: - """ - :param str app_id: Microsoft Teams application id. - :keyword cloud: Cloud environment that the application belongs to. Default value is `PUBLIC`. - :paramtype cloud: str or ~azure.communication.chat.CommunicationCloudEnvironment - :keyword str raw_id: The raw ID of the identifier. If not specified, this value will be constructed - from the other properties. - """ - self.properties = cast( - MicrosoftTeamsAppProperties, - _botbackcompatdict( - app_id=app_id, - cloud=kwargs.get("cloud") or CommunicationCloudEnvironment.PUBLIC, - ), - ) - raw_id: Optional[str] = kwargs.get("raw_id") - self.raw_id = raw_id if raw_id is not None else self._format_raw_id(self.properties) - - def __eq__(self, other): - try: - if other.raw_id: - return self.raw_id == other.raw_id - return self.raw_id == self._format_raw_id(other.properties) - except Exception: # pylint: disable=broad-except - return False - - def _format_raw_id(self, properties: MicrosoftTeamsAppProperties) -> str: - app_id = properties["app_id"] - cloud = properties["cloud"] - if cloud == CommunicationCloudEnvironment.DOD: - return f"{TEAMS_APP_DOD_CLOUD_PREFIX}{app_id}" - if cloud == CommunicationCloudEnvironment.GCCH: - return f"{TEAMS_APP_GCCH_CLOUD_PREFIX}{app_id}" - return f"{TEAMS_APP_PUBLIC_CLOUD_PREFIX}{app_id}" - - -class _MicrosoftBotIdentifier(MicrosoftTeamsAppIdentifier): - """Represents an identifier for a Microsoft bot. - - DEPRECATED. Only used in cases of backwards compatibility. - """ - - def __init__(self, bot_id, **kwargs): - """ - :param str bot_id: Microsoft bot id. - :keyword bool is_resource_account_configured: `False` if the identifier is global. - Default value is `True` for tennantzed bots. - :keyword cloud: Cloud environment that the bot belongs to. Default value is `PUBLIC`. - :paramtype cloud: str or ~azure.communication.chat.CommunicationCloudEnvironment - """ - warnings.warn( - "The MicrosoftBotIdentifier is deprecated and has been replaced by MicrosoftTeamsAppIdentifier.", - DeprecationWarning, - ) - super().__init__(bot_id, **kwargs) - - -def identifier_from_raw_id(raw_id: str) -> CommunicationIdentifier: # pylint: disable=too-many-return-statements - """ - Creates a CommunicationIdentifier from a given raw ID. - - When storing raw IDs use this function to restore the identifier that was encoded in the raw ID. - - :param str raw_id: A raw ID to construct the CommunicationIdentifier from. - :return: The CommunicationIdentifier parsed from the raw_id. - :rtype: CommunicationIdentifier - """ - if raw_id.startswith(PHONE_NUMBER_PREFIX): - return PhoneNumberIdentifier(value=raw_id[len(PHONE_NUMBER_PREFIX) :], raw_id=raw_id) - - segments = raw_id.split(":", maxsplit=2) - if len(segments) < 3: - return UnknownIdentifier(identifier=raw_id) - - prefix = f"{segments[0]}:{segments[1]}:" - suffix = segments[2] - if prefix == TEAMS_USER_ANONYMOUS_PREFIX: - return MicrosoftTeamsUserIdentifier(user_id=suffix, is_anonymous=True, raw_id=raw_id) - if prefix == TEAMS_USER_PUBLIC_CLOUD_PREFIX: - return MicrosoftTeamsUserIdentifier( - user_id=suffix, - is_anonymous=False, - cloud=CommunicationCloudEnvironment.PUBLIC, - raw_id=raw_id, - ) - if prefix == TEAMS_USER_DOD_CLOUD_PREFIX: - return MicrosoftTeamsUserIdentifier( - user_id=suffix, - is_anonymous=False, - cloud=CommunicationCloudEnvironment.DOD, - raw_id=raw_id, - ) - if prefix == TEAMS_USER_GCCH_CLOUD_PREFIX: - return MicrosoftTeamsUserIdentifier( - user_id=suffix, - is_anonymous=False, - cloud=CommunicationCloudEnvironment.GCCH, - raw_id=raw_id, - ) - if prefix == TEAMS_APP_PUBLIC_CLOUD_PREFIX: - return MicrosoftTeamsAppIdentifier( - app_id=suffix, - cloud=CommunicationCloudEnvironment.PUBLIC, - raw_id=raw_id, - ) - if prefix == TEAMS_APP_DOD_CLOUD_PREFIX: - return MicrosoftTeamsAppIdentifier( - app_id=suffix, - cloud=CommunicationCloudEnvironment.DOD, - raw_id=raw_id, - ) - if prefix == TEAMS_APP_GCCH_CLOUD_PREFIX: - return MicrosoftTeamsAppIdentifier( - app_id=suffix, - cloud=CommunicationCloudEnvironment.GCCH, - raw_id=raw_id, - ) - if prefix in [ - ACS_USER_PREFIX, - ACS_USER_DOD_CLOUD_PREFIX, - ACS_USER_GCCH_CLOUD_PREFIX, - SPOOL_USER_PREFIX, - ]: - return CommunicationUserIdentifier(id=raw_id, raw_id=raw_id) - return UnknownIdentifier(identifier=raw_id) diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/policy.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/policy.py deleted file mode 100644 index 1843d22e83a2..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/policy.py +++ /dev/null @@ -1,120 +0,0 @@ -# ------------------------------------------------------------------------ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# ------------------------------------------------------------------------- - -import hashlib -import urllib -import base64 -import hmac -from urllib.parse import ParseResult, urlparse -from typing import Union -from azure.core.credentials import AzureKeyCredential -from azure.core.pipeline.policies import SansIOHTTPPolicy -from .utils import get_current_utc_time - - -class HMACCredentialsPolicy(SansIOHTTPPolicy): - """Implementation of HMAC authentication policy. - - :param str host: The host of the endpoint url for Azure Communication Service resource - :param access_key: The access key we use to authenticate to the service - :type access_key: str or AzureKeyCredential - :param bool decode_url: `True` if there is a need to decode the url. Default value is `False` - """ - - def __init__( - self, - host: str, - access_key: Union[str, AzureKeyCredential], - decode_url: bool = False, - ) -> None: - super(HMACCredentialsPolicy, self).__init__() - - if host.startswith("https://"): - self._host = host.replace("https://", "") - - if host.startswith("http://"): - self._host = host.replace("http://", "") - - self._access_key = access_key - self._decode_url = decode_url - - def _compute_hmac( - self, value # type: str - ): - if isinstance(self._access_key, AzureKeyCredential): - decoded_secret = base64.b64decode(self._access_key.key) - else: - decoded_secret = base64.b64decode(self._access_key) - - digest = hmac.new(decoded_secret, value.encode("utf-8"), hashlib.sha256).digest() - - return base64.b64encode(digest).decode("utf-8") - - def _sign_request(self, request): - verb = request.http_request.method.upper() - - # Get the path and query from url, which looks like https://host/path/query - parsed_url: ParseResult = urlparse(request.http_request.url) - query_url = parsed_url.path - - if parsed_url.query: - query_url += "?" + parsed_url.query - - # Need URL() to get a correct encoded key value, from "%3A" to ":", when transport is in type AioHttpTransport. - # There's a similar scenario in azure-storage-blob and azure-appconfiguration, the check logic is from there. - try: - from yarl import URL - from azure.core.pipeline.transport import ( # pylint:disable=non-abstract-transport-import - AioHttpTransport, - ) - - if ( - isinstance(request.context.transport, AioHttpTransport) - or isinstance( - getattr(request.context.transport, "_transport", None), - AioHttpTransport, - ) - or isinstance( - getattr( - getattr(request.context.transport, "_transport", None), - "_transport", - None, - ), - AioHttpTransport, - ) - ): - query_url = str(URL(query_url)) - except (ImportError, TypeError): - pass - - if self._decode_url: - query_url = urllib.parse.unquote(query_url) - - signed_headers = "x-ms-date;host;x-ms-content-sha256" - - utc_now = get_current_utc_time() - if request.http_request.body is None: - request.http_request.body = "" - content_digest = hashlib.sha256((request.http_request.body.encode("utf-8"))).digest() - content_hash = base64.b64encode(content_digest).decode("utf-8") - - string_to_sign = verb + "\n" + query_url + "\n" + utc_now + ";" + self._host + ";" + content_hash - - signature = self._compute_hmac(string_to_sign) - - signature_header = { - "x-ms-date": utc_now, - "x-ms-content-sha256": content_hash, - "x-ms-return-client-request-id": "true", - "Authorization": "HMAC-SHA256 SignedHeaders=" + signed_headers + "&Signature=" + signature, - } - - request.http_request.headers.update(signature_header) - - return request - - def on_request(self, request): - self._sign_request(request) diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential.py deleted file mode 100644 index 54603e7b32ce..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential.py +++ /dev/null @@ -1,143 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# -------------------------------------------------------------------------- - -from threading import Lock, Condition, Timer, TIMEOUT_MAX, Event -from datetime import timedelta -from typing import Any - -from .utils import get_current_utc_as_int -from .utils import create_access_token - - -class CommunicationTokenCredential(object): - """Credential type used for authenticating to an Azure Communication service. - :param str token: The token used to authenticate to an Azure Communication service. - :keyword token_refresher: The sync token refresher to provide capacity to fetch a fresh token. - The returned token must be valid (expiration date must be in the future). - :paramtype token_refresher: Callable[[], AccessToken] - :keyword bool proactive_refresh: Whether to refresh the token proactively or not. - If the proactive refreshing is enabled ('proactive_refresh' is true), the credential will use - a background thread to attempt to refresh the token within 10 minutes before the cached token expires, - the proactive refresh will request a new token by calling the 'token_refresher' callback. - When 'proactive_refresh' is enabled, the Credential object must be either run within a context manager - or the 'close' method must be called once the object usage has been finished. - :raises: TypeError if paramater 'token' is not a string - :raises: ValueError if the 'proactive_refresh' is enabled without providing the 'token_refresher' callable. - """ - - _ON_DEMAND_REFRESHING_INTERVAL_MINUTES = 2 - _DEFAULT_AUTOREFRESH_INTERVAL_MINUTES = 10 - - def __init__(self, token: str, **kwargs: Any): - if not isinstance(token, str): - raise TypeError("Token must be a string.") - self._token = create_access_token(token) - self._token_refresher = kwargs.pop("token_refresher", None) - self._proactive_refresh = kwargs.pop("proactive_refresh", False) - if self._proactive_refresh and self._token_refresher is None: - raise ValueError("When 'proactive_refresh' is True, 'token_refresher' must not be None.") - self._timer = None - self._lock = Condition(Lock()) - self._some_thread_refreshing = False - self._is_closed = Event() - - def get_token(self, *scopes, **kwargs): # pylint: disable=unused-argument - # type (*str, **Any) -> AccessToken - """The value of the configured token. - :param any scopes: Scopes to be added to the token. - :return: AccessToken - :rtype: ~azure.core.credentials.AccessToken - """ - if self._proactive_refresh and self._is_closed.is_set(): - raise RuntimeError("An instance of CommunicationTokenCredential cannot be reused once it has been closed.") - - if not self._token_refresher or not self._is_token_expiring_soon(self._token): - return self._token - self._update_token_and_reschedule() - return self._token - - def _update_token_and_reschedule(self): - should_this_thread_refresh = False - with self._lock: - while self._is_token_expiring_soon(self._token): - if self._some_thread_refreshing: - if self._is_token_valid(self._token): - return self._token - self._wait_till_lock_owner_finishes_refreshing() - else: - should_this_thread_refresh = True - self._some_thread_refreshing = True - break - - if should_this_thread_refresh: - try: - new_token = self._token_refresher() - if not self._is_token_valid(new_token): - raise ValueError("The token returned from the token_refresher is expired.") - with self._lock: - self._token = new_token - self._some_thread_refreshing = False - self._lock.notify_all() - except: - with self._lock: - self._some_thread_refreshing = False - self._lock.notify_all() - raise - if self._proactive_refresh: - self._schedule_refresh() - return self._token - - def _schedule_refresh(self): - if self._is_closed.is_set(): - return - if self._timer is not None: - self._timer.cancel() - - token_ttl = self._token.expires_on - get_current_utc_as_int() - - if self._is_token_expiring_soon(self._token): - # Schedule the next refresh for when it reaches a certain percentage of the remaining lifetime. - timespan = token_ttl // 2 - else: - # Schedule the next refresh for when it gets in to the soon-to-expire window. - timespan = token_ttl - timedelta(minutes=self._DEFAULT_AUTOREFRESH_INTERVAL_MINUTES).total_seconds() - if timespan <= TIMEOUT_MAX: - self._timer = Timer(timespan, self._update_token_and_reschedule) - self._timer.daemon = True - self._timer.start() - - def _wait_till_lock_owner_finishes_refreshing(self): - self._lock.release() - self._lock.acquire() - - def _is_token_expiring_soon(self, token): - if self._proactive_refresh: - interval = timedelta(minutes=self._DEFAULT_AUTOREFRESH_INTERVAL_MINUTES) - else: - interval = timedelta(minutes=self._ON_DEMAND_REFRESHING_INTERVAL_MINUTES) - return (token.expires_on - get_current_utc_as_int()) < interval.total_seconds() - - @classmethod - def _is_token_valid(cls, token): - return get_current_utc_as_int() < token.expires_on - - def __enter__(self): - if self._proactive_refresh: - if self._is_closed.is_set(): - raise RuntimeError( - "An instance of CommunicationTokenCredential cannot be reused once it has been closed." - ) - self._schedule_refresh() - return self - - def __exit__(self, *args): - self.close() - - def close(self) -> None: - if self._timer is not None: - self._timer.cancel() - self._timer = None - self._is_closed.set() diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential_async.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential_async.py deleted file mode 100644 index c55896c5b6bb..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential_async.py +++ /dev/null @@ -1,148 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# -------------------------------------------------------------------------- -# pylint: disable=C4763 -from asyncio import Condition, Lock, Event -from datetime import timedelta -from typing import Any -import sys - -from .utils import get_current_utc_as_int -from .utils import create_access_token -from .utils_async import AsyncTimer - - -class CommunicationTokenCredential(object): - """Credential type used for authenticating to an Azure Communication service. - :param str token: The token used to authenticate to an Azure Communication service. - :keyword token_refresher: The async token refresher to provide capacity to fetch a fresh token. - The returned token must be valid (expiration date must be in the future). - :paramtype token_refresher: Callable[[], Awaitable[AccessToken]] - :keyword bool proactive_refresh: Whether to refresh the token proactively or not. - If the proactive refreshing is enabled ('proactive_refresh' is true), the credential will use - a background thread to attempt to refresh the token within 10 minutes before the cached token expires, - the proactive refresh will request a new token by calling the 'token_refresher' callback. - When 'proactive_refresh is enabled', the Credential object must be either run within a context manager - or the 'close' method must be called once the object usage has been finished. - :raises: TypeError if paramater 'token' is not a string - :raises: ValueError if the 'proactive_refresh' is enabled without providing the 'token_refresher' function. - """ - - _ON_DEMAND_REFRESHING_INTERVAL_MINUTES = 2 - _DEFAULT_AUTOREFRESH_INTERVAL_MINUTES = 10 - - def __init__(self, token: str, **kwargs: Any): - if not isinstance(token, str): - raise TypeError("Token must be a string.") - self._token = create_access_token(token) - self._token_refresher = kwargs.pop("token_refresher", None) - self._proactive_refresh = kwargs.pop("proactive_refresh", False) - if self._proactive_refresh and self._token_refresher is None: - raise ValueError("When 'proactive_refresh' is True, 'token_refresher' must not be None.") - self._timer = None - self._async_mutex = Lock() - if sys.version_info[:3] == (3, 10, 0): - # Workaround for Python 3.10 bug(https://bugs.python.org/issue45416): - getattr(self._async_mutex, "_get_loop", lambda: None)() - self._lock = Condition(self._async_mutex) - self._some_thread_refreshing = False - self._is_closed = Event() - - async def get_token(self, *scopes, **kwargs): # pylint: disable=unused-argument - # type (*str, **Any) -> AccessToken - """The value of the configured token. - :param any scopes: Scopes to be added to the token. - :return: AccessToken - :rtype: ~azure.core.credentials.AccessToken - """ - if self._proactive_refresh and self._is_closed.is_set(): - raise RuntimeError("An instance of CommunicationTokenCredential cannot be reused once it has been closed.") - - if not self._token_refresher or not self._is_token_expiring_soon(self._token): - return self._token - await self._update_token_and_reschedule() - return self._token - - async def _update_token_and_reschedule(self): - should_this_thread_refresh = False - async with self._lock: - while self._is_token_expiring_soon(self._token): - if self._some_thread_refreshing: - if self._is_token_valid(self._token): - return self._token - await self._wait_till_lock_owner_finishes_refreshing() - else: - should_this_thread_refresh = True - self._some_thread_refreshing = True - break - - if should_this_thread_refresh: - try: - new_token = await self._token_refresher() - if not self._is_token_valid(new_token): - raise ValueError("The token returned from the token_refresher is expired.") - async with self._lock: - self._token = new_token - self._some_thread_refreshing = False - self._lock.notify_all() - except: - async with self._lock: - self._some_thread_refreshing = False - self._lock.notify_all() - raise - if self._proactive_refresh: - self._schedule_refresh() - return self._token - - def _schedule_refresh(self): - if self._is_closed.is_set(): - return - if self._timer is not None: - self._timer.cancel() - - token_ttl = self._token.expires_on - get_current_utc_as_int() - - if self._is_token_expiring_soon(self._token): - # Schedule the next refresh for when it reaches a certain percentage of the remaining lifetime. - timespan = token_ttl // 2 - else: - # Schedule the next refresh for when it gets in to the soon-to-expire window. - timespan = token_ttl - timedelta(minutes=self._DEFAULT_AUTOREFRESH_INTERVAL_MINUTES).total_seconds() - - self._timer = AsyncTimer(timespan, self._update_token_and_reschedule) - self._timer.start() - - async def _wait_till_lock_owner_finishes_refreshing(self): - self._lock.release() - await self._lock.acquire() - - def _is_token_expiring_soon(self, token): - if self._proactive_refresh: - interval = timedelta(minutes=self._DEFAULT_AUTOREFRESH_INTERVAL_MINUTES) - else: - interval = timedelta(minutes=self._ON_DEMAND_REFRESHING_INTERVAL_MINUTES) - return (token.expires_on - get_current_utc_as_int()) < interval.total_seconds() - - @classmethod - def _is_token_valid(cls, token): - return get_current_utc_as_int() < token.expires_on - - async def __aenter__(self): - if self._proactive_refresh: - if self._is_closed.is_set(): - raise RuntimeError( - "An instance of CommunicationTokenCredential cannot be reused once it has been closed." - ) - self._schedule_refresh() - return self - - async def __aexit__(self, *args): - await self.close() - - async def close(self) -> None: - if self._timer is not None: - self._timer.cancel() - self._timer = None - self._is_closed.set() diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils.py deleted file mode 100644 index 38a62a49dc3f..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils.py +++ /dev/null @@ -1,89 +0,0 @@ -# ------------------------------------------------------------------------ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# ------------------------------------------------------------------------- - -import base64 -import json -import calendar -from typing import cast, Tuple, Optional -from datetime import datetime -from azure.core.serialization import TZ_UTC -from azure.core.credentials import AccessToken - - -def _convert_datetime_to_utc_int(input_datetime) -> int: - """ - Converts DateTime in local time to the Epoch in UTC in second. - - :param input_datetime: Input datetime - :type input_datetime: datetime - :return: Integer - :rtype: int - """ - return int(calendar.timegm(input_datetime.utctimetuple())) - - -def parse_connection_str(conn_str: Optional[str]) -> Tuple[str, str]: - if conn_str is None: - raise ValueError("Connection string is undefined.") - endpoint = None - shared_access_key = None - for element in conn_str.split(";"): - key, _, value = element.partition("=") - if key.lower() == "endpoint": - endpoint = value.rstrip("/") - elif key.lower() == "accesskey": - shared_access_key = value - if not all([endpoint, shared_access_key]): - raise ValueError( - "Invalid connection string. You can get the connection string from your resource page in the Azure Portal. " - "The format should be as follows: endpoint=https:///;accesskey=" - ) - left_slash_pos = cast(str, endpoint).find("//") - if left_slash_pos != -1: - host = cast(str, endpoint)[left_slash_pos + 2 :] - else: - host = str(endpoint) - - return host, str(shared_access_key) - - -def get_current_utc_time() -> str: - return str(datetime.now(tz=TZ_UTC).strftime("%a, %d %b %Y %H:%M:%S ")) + "GMT" - - -def get_current_utc_as_int() -> int: - current_utc_datetime = datetime.utcnow() - return _convert_datetime_to_utc_int(current_utc_datetime) - - -def create_access_token(token) -> AccessToken: - """Creates an instance of azure.core.credentials.AccessToken from a - string token. The input string is jwt token in the following form: - .. - This method looks into the token_payload which is a json and extracts the expiry time - for that token and creates a tuple of type azure.core.credentials.AccessToken - (, ) - :param token: User token - :type token: str - :return: Instance of azure.core.credentials.AccessToken - token and expiry date of it - :rtype: ~azure.core.credentials.AccessToken - """ - - token_parse_err_msg = "Token is not formatted correctly" - parts = token.split(".") - - if len(parts) < 3: - raise ValueError(token_parse_err_msg) - - try: - padded_base64_payload = base64.b64decode(parts[1] + "==").decode("ascii") - payload = json.loads(padded_base64_payload) - return AccessToken( - token, - _convert_datetime_to_utc_int(datetime.fromtimestamp(payload["exp"], TZ_UTC)), - ) - except ValueError as val_error: - raise ValueError(token_parse_err_msg) from val_error diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils_async.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils_async.py deleted file mode 100644 index 7402d088a880..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils_async.py +++ /dev/null @@ -1,30 +0,0 @@ -# ------------------------------------------------------------------------ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# ------------------------------------------------------------------------- -# pylint: disable=C4763 -from asyncio import sleep, ensure_future - -class AsyncTimer: - """A non-blocking timer, that calls a function after a specified number of seconds: - :param int interval: time interval in seconds - :param callable callback: function to be called after the interval has elapsed - """ - - def __init__(self, interval, callback): - self._interval = interval - self._callback = callback - self._task = None - - def start(self): - self._task = ensure_future(self._job()) - - async def _job(self): - await sleep(self._interval) - await self._callback() - - def cancel(self): - if self._task is not None: - self._task.cancel() - self._task = None diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_types.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_types.py deleted file mode 100644 index 1fe86657cb0f..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_types.py +++ /dev/null @@ -1,12 +0,0 @@ -# coding=utf-8 -# 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 license information. -# Code generated by Microsoft (R) Python Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- - -from typing import Literal - -RepeatabilityResult = Literal["accepted", "rejected"] diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_version.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_version.py index 5bf479b145f7..0ec13ea52bbf 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_version.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_version.py @@ -6,4 +6,4 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -VERSION = "1.2.0b1" +VERSION = "1.0.0" diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_client.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_client.py index 71066f8c89ea..40010410b4b3 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_client.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_client.py @@ -27,10 +27,11 @@ class NotificationMessagesClient(NotificationMessagesClientOperationsMixin): """NotificationMessagesClient. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials_async.AsyncTokenCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is @@ -110,10 +111,11 @@ class MessageTemplateClient(MessageTemplateClientOperationsMixin): """MessageTemplateClient. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials_async.AsyncTokenCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_configuration.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_configuration.py index abd8e1a53b27..413b8177152f 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_configuration.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_configuration.py @@ -24,10 +24,11 @@ class NotificationMessagesClientConfiguration: # pylint: disable=too-many-insta attributes. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials_async.AsyncTokenCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is @@ -82,10 +83,11 @@ class MessageTemplateClientConfiguration: # pylint: disable=too-many-instance-a attributes. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials_async.AsyncTokenCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_operations.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_operations.py index 574698b25cdb..355c433d272f 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_operations.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_operations.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding=utf-8 # -------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. @@ -308,7 +309,7 @@ def prepare_request(next_link=None): async def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize(List[_models.MessageTemplateItem], deserialized["value"]) + list_of_elem = _deserialize(List[_models.MessageTemplateItem], deserialized.get("value", [])) if cls: list_of_elem = cls(list_of_elem) # type: ignore return deserialized.get("nextLink") or None, AsyncList(list_of_elem) diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_patch.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_patch.py index f7dd32510333..8bcb627aa475 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_patch.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_patch.py @@ -1,7 +1,8 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------- """Customize generated code here. Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_patch.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_patch.py index d69ae3068ceb..8bcb627aa475 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_patch.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_patch.py @@ -1,144 +1,15 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------- """Customize generated code here. Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ -from typing import ( - List, - Any, - Union, -) -from urllib.parse import urlparse -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from .._shared.utils import parse_connection_str -from ._client import ( - NotificationMessagesClient as NotificationMessagesClientGenerated, - MessageTemplateClient as MessageTemplateClientGenerated, -) -from .._api_versions import DEFAULT_VERSION -from .._shared.auth_policy_utils import get_authentication_policy +from typing import List - -class NotificationMessagesClient(NotificationMessagesClientGenerated): - """A client to interact with the AzureCommunicationService Messaging service. - - This client allows you to send and receive WhatsApp template messages using the - Azure Communication Services Messaging SDK. - - :param str endpoint: - The endpoint of the Azure Communication resource. - :param ~azure.core.credentials.AzureKeyCredential credential: - The credentials with which to authenticate - :keyword api_version: Azure Communication Messaging API version. - Default value is "2024-02-01". - Note that overriding this default value may result in unsupported behavior. - """ - - def __init__( - self, endpoint: str, credential: Union[AsyncTokenCredential, AzureKeyCredential], **kwargs: Any - ) -> None: - if not credential: - raise ValueError("credential can not be None") - - try: - if not endpoint.lower().startswith("http"): - endpoint = "https://" + endpoint - except AttributeError: - raise ValueError("Host URL must be a string") # pylint:disable=raise-missing-from - - parsed_url = urlparse(endpoint.rstrip("/")) - if not parsed_url.netloc: - raise ValueError("Invalid URL: {}".format(endpoint)) - - self._endpoint = endpoint - self._credential = credential - self._authentication_policy = get_authentication_policy(endpoint, credential) - self._api_version = kwargs.pop("api_version", DEFAULT_VERSION) - super().__init__( - self._endpoint, - self._credential, - authentication_policy=self._authentication_policy, - api_version=self._api_version, - **kwargs - ) - - @classmethod - def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "NotificationMessagesClient": - """Create NotificationMessagesClient from a Connection String. - - :param conn_str: Azure Communication Service endpoint. Required. - :type conn_str: str - :return: instance of NotificationMessagesClient. - :rtype: ~azure.communication.message.NotificationMessagesClient - """ - endpoint, access_key = parse_connection_str(conn_str) - return cls(endpoint, AzureKeyCredential(key=access_key), **kwargs) - - -class MessageTemplateClient(MessageTemplateClientGenerated): - """A client to interact with the AzureCommunicationService Messaging service. - - This client allows you to send and receive WhatsApp template - messages using the Azure Communication Services Messaging SDK. - - :param str endpoint: - The endpoint of the Azure Communication resource. - :param ~azure.core.credentials.AzureKeyCredential credential: - The credentials with which to authenticate - :keyword api_version: Azure Communication Messaging API version. Default value is "2024-02-01". - Note that overriding this default value may result in unsupported behavior. - :paramtype api_version: str - """ - - def __init__( - self, endpoint: str, credential: Union[AsyncTokenCredential, AzureKeyCredential], **kwargs: Any - ) -> "None": - if not credential: - raise ValueError("credential can not be None") - - try: - if not endpoint.lower().startswith("http"): - endpoint = "https://" + endpoint - except AttributeError: - raise ValueError("Host URL must be a string") # pylint: disable=raise-missing-from - - parsed_url = urlparse(endpoint.rstrip("/")) - if not parsed_url.netloc: - raise ValueError("Invalid URL: {}".format(endpoint)) - - self._endpoint = endpoint - self._credential = credential - self._authentication_policy = get_authentication_policy(endpoint, credential) - self._api_version = kwargs.pop("api_version", DEFAULT_VERSION) - super().__init__( - self._endpoint, - self._credential, - authentication_policy=self._authentication_policy, - api_version=self._api_version, - **kwargs - ) - - @classmethod - def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "MessageTemplateClient": - """Create MessageTemplateClient from a Connection String. - - :param conn_str: Azure Communication Service endpoint. Required. - :type conn_str: str - :return: instance of MessageTemplateClient. - :rtype: ~azure.communication.message.MessageTemplateClient - """ - endpoint, access_key = parse_connection_str(conn_str) - return cls(endpoint, AzureKeyCredential(access_key), **kwargs) - - -__all__: List[str] = [ - "NotificationMessagesClient", - "MessageTemplateClient", -] # Add all objects you want publicly available to users at this package level +__all__: List[str] = [] # Add all objects you want publicly available to users at this package level def patch_sdk(): diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/models/_enums.py b/sdk/communication/azure-communication-messages/azure/communication/messages/models/_enums.py index 886dcda444f3..5308c0845c09 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/models/_enums.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/models/_enums.py @@ -39,7 +39,7 @@ class CommunicationMessageKind(str, Enum, metaclass=CaseInsensitiveEnumMeta): class CommunicationMessagesChannel(str, Enum, metaclass=CaseInsensitiveEnumMeta): """The type of the communication messages channel.""" - WHATSAPP = "whatsApp" + WHATS_APP = "whatsApp" """The WhatsApp communication messages channel type.""" @@ -76,7 +76,7 @@ class MessageContentKind(str, Enum, metaclass=CaseInsensitiveEnumMeta): class MessageTemplateBindingsKind(str, Enum, metaclass=CaseInsensitiveEnumMeta): """The type of the message template.""" - WHATSAPP = "whatsApp" + WHATS_APP = "whatsApp" """The WhatsApp template type.""" diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/models/_models.py b/sdk/communication/azure-communication-messages/azure/communication/messages/models/_models.py index 1c601a64031b..5bc37f9d6434 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/models/_models.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/models/_models.py @@ -1,4 +1,4 @@ -# pylint: disable=too-many-lines +# pylint: disable=line-too-long,useless-suppression,too-many-lines # coding=utf-8 # -------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. @@ -31,15 +31,13 @@ class ActionBindings(_model_base.Model): You probably want to use the sub-classes and not this class directly. Known sub-classes are: WhatsAppButtonActionBindings, WhatsAppListActionBindings, WhatsAppUrlActionBindings - All required parameters must be populated in order to send to server. - :ivar kind: Kind of the MessageActionBinding. Required. Known values are: "whatsAppListAction", "whatsAppButtonAction", and "whatsAppUrlAction". :vartype kind: str or ~azure.communication.messages.models.MessageActionBindingKind """ __mapping__: Dict[str, _model_base.Model] = {} - kind: str = rest_discriminator(name="kind") + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) """Kind of the MessageActionBinding. Required. Known values are: \"whatsAppListAction\", \"whatsAppButtonAction\", and \"whatsAppUrlAction\".""" @@ -64,17 +62,17 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ActionGroup(_model_base.Model): """The Action Group content. - All required parameters must be populated in order to send to server. - :ivar title: Title of the ActionGroup. Required. :vartype title: str :ivar items_property: Array of items in ActionGroup. Required. :vartype items_property: list[~azure.communication.messages.models.ActionGroupItem] """ - title: str = rest_field() + title: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Title of the ActionGroup. Required.""" - items_property: List["_models.ActionGroupItem"] = rest_field(name="items") + items_property: List["_models.ActionGroupItem"] = rest_field( + name="items", visibility=["read", "create", "update", "delete", "query"] + ) """Array of items in ActionGroup. Required.""" @overload @@ -103,15 +101,13 @@ class MessageContent(_model_base.Model): ButtonSetContent, DocumentMessageContent, ActionGroupContent, ImageMessageContent, TextMessageContent, LinkContent, VideoMessageContent - All required parameters must be populated in order to send to server. - :ivar kind: Kind of MessageContent. Required. Known values are: "text", "image", "video", "document", "group", "buttonSet", and "url". :vartype kind: str or ~azure.communication.messages.models.MessageContentKind """ __mapping__: Dict[str, _model_base.Model] = {} - kind: str = rest_discriminator(name="kind") + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) """Kind of MessageContent. Required. Known values are: \"text\", \"image\", \"video\", \"document\", \"group\", \"buttonSet\", and \"url\".""" @@ -136,8 +132,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ActionGroupContent(MessageContent, discriminator="group"): """The action content of type ActionGroup. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is actionGroup. Required. The ActionSet content type. :vartype kind: str or ~azure.communication.messages.models.GROUP :ivar title: Title of the actionGroup content. Required. @@ -146,11 +140,11 @@ class ActionGroupContent(MessageContent, discriminator="group"): :vartype groups: list[~azure.communication.messages.models.ActionGroup] """ - kind: Literal[MessageContentKind.GROUP] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.GROUP] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is actionGroup. Required. The ActionSet content type.""" - title: str = rest_field() + title: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Title of the actionGroup content. Required.""" - groups: List["_models.ActionGroup"] = rest_field() + groups: List["_models.ActionGroup"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Set or group of actions. Required.""" @overload @@ -175,8 +169,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ActionGroupItem(_model_base.Model): """The Action group item in the content. - All required parameters must be populated in order to send to server. - :ivar id: Id of the Item. Required. :vartype id: str :ivar title: Title of the Item. Required. @@ -185,11 +177,11 @@ class ActionGroupItem(_model_base.Model): :vartype description: str """ - id: str = rest_field() + id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Id of the Item. Required.""" - title: str = rest_field() + title: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Title of the Item. Required.""" - description: str = rest_field() + description: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Description of the Item. Required.""" @overload @@ -221,8 +213,6 @@ class NotificationContent(_model_base.Model): StickerNotificationContent, TemplateNotificationContent, TextNotificationContent, VideoNotificationContent - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -235,11 +225,13 @@ class NotificationContent(_model_base.Model): """ __mapping__: Dict[str, _model_base.Model] = {} - channel_registration_id: str = rest_field(name="channelRegistrationId") + channel_registration_id: str = rest_field( + name="channelRegistrationId", visibility=["read", "create", "update", "delete", "query"] + ) """The Channel Registration ID for the Business Identifier. Required.""" - to: List[str] = rest_field() + to: List[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The native external platform user identifiers of the recipient. Required.""" - kind: str = rest_discriminator(name="kind") + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) """The type discriminator describing a notification type. Required. Known values are: \"text\", \"image\", \"image_v0\", \"document\", \"video\", \"audio\", \"template\", \"sticker\", \"reaction\", and \"interactive\".""" @@ -267,8 +259,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class AudioNotificationContent(NotificationContent, discriminator="audio"): """A request to send an audio notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -281,9 +271,9 @@ class AudioNotificationContent(NotificationContent, discriminator="audio"): :vartype media_uri: str """ - kind: Literal[CommunicationMessageKind.AUDIO] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.AUDIO] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is audio. Required. Audio message type.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """A media url for the file. Required if the type is one of the supported media types, e.g. image. Required.""" @@ -310,17 +300,15 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ButtonContent(_model_base.Model): """The message content of type Button information. - All required parameters must be populated in order to send to server. - :ivar id: Unique Id of the button content. Required. :vartype id: str :ivar title: Title of the button content. Required. :vartype title: str """ - id: str = rest_field() + id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Unique Id of the button content. Required.""" - title: str = rest_field() + title: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Title of the button content. Required.""" @overload @@ -345,17 +333,15 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ButtonSetContent(MessageContent, discriminator="buttonSet"): """The message content of type ButtonSet/ List of buttons information. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is Button. Required. The ButtonSet content type. :vartype kind: str or ~azure.communication.messages.models.BUTTON_SET :ivar buttons: Unique Id of the button content. Required. :vartype buttons: list[~azure.communication.messages.models.ButtonContent] """ - kind: Literal[MessageContentKind.BUTTON_SET] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.BUTTON_SET] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is Button. Required. The ButtonSet content type.""" - buttons: List["_models.ButtonContent"] = rest_field() + buttons: List["_models.ButtonContent"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Unique Id of the button content. Required.""" @overload @@ -379,17 +365,15 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class DocumentMessageContent(MessageContent, discriminator="document"): """The message content of type document information. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is document. Required. The document content type. :vartype kind: str or ~azure.communication.messages.models.DOCUMENT :ivar media_uri: MediaUri of the media content. Required. :vartype media_uri: str """ - kind: Literal[MessageContentKind.DOCUMENT] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.DOCUMENT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is document. Required. The document content type.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """MediaUri of the media content. Required.""" @overload @@ -413,8 +397,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class DocumentNotificationContent(NotificationContent, discriminator="document"): """A request to send a document notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -431,13 +413,13 @@ class DocumentNotificationContent(NotificationContent, discriminator="document") :vartype media_uri: str """ - kind: Literal[CommunicationMessageKind.DOCUMENT] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.DOCUMENT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is image. Required. Document message type.""" - caption: Optional[str] = rest_field() + caption: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Optional text content.""" - file_name: Optional[str] = rest_field(name="fileName") + file_name: Optional[str] = rest_field(name="fileName", visibility=["read", "create", "update", "delete", "query"]) """Optional name for the file.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """A media url for the file. Required if the type is one of the supported media types, e.g. image. Required.""" @@ -466,17 +448,15 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ImageMessageContent(MessageContent, discriminator="image"): """The message content of type image information. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is image. Required. The image content type. :vartype kind: str or ~azure.communication.messages.models.IMAGE :ivar media_uri: MediaUri of the media content. Required. :vartype media_uri: str """ - kind: Literal[MessageContentKind.IMAGE] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.IMAGE] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is image. Required. The image content type.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """MediaUri of the media content. Required.""" @overload @@ -500,8 +480,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ImageNotificationContent(NotificationContent, discriminator="image"): """A request to send an image notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -516,11 +494,11 @@ class ImageNotificationContent(NotificationContent, discriminator="image"): :vartype media_uri: str """ - kind: Literal[CommunicationMessageKind.IMAGE] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.IMAGE] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is image. Required. Image message type.""" - content: Optional[str] = rest_field(name="caption") + content: Optional[str] = rest_field(name="caption", visibility=["read", "create", "update", "delete", "query"]) """Optional text content.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """A media url for the file. Required if the type is one of the supported media types, e.g. image. Required.""" @@ -548,8 +526,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class InteractiveMessage(_model_base.Model): """The Interactive message content to which user can read and respond. - All required parameters must be populated in order to send to server. - :ivar header: Gets or Sets Header content. Supports the following types:text, images etc. :vartype header: ~azure.communication.messages.models.MessageContent :ivar body: Gets or Sets Message body content. Emojis, markdown, and links are supported. @@ -562,13 +538,15 @@ class InteractiveMessage(_model_base.Model): :vartype action: ~azure.communication.messages.models.ActionBindings """ - header: Optional["_models.MessageContent"] = rest_field() + header: Optional["_models.MessageContent"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Gets or Sets Header content. Supports the following types:text, images etc.""" - body: "_models.TextMessageContent" = rest_field() + body: "_models.TextMessageContent" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Gets or Sets Message body content. Emojis, markdown, and links are supported. Required.""" - footer: Optional["_models.TextMessageContent"] = rest_field() + footer: Optional["_models.TextMessageContent"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """Gets or Sets Message footer content. Emojis, markdown, and links are supported.""" - action: "_models.ActionBindings" = rest_field() + action: "_models.ActionBindings" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The binding object to get or set Action which describes options user have to respond to message. Required.""" @@ -596,8 +574,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class InteractiveNotificationContent(NotificationContent, discriminator="interactive"): """A request to send an Interactive message notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -610,9 +586,11 @@ class InteractiveNotificationContent(NotificationContent, discriminator="interac :vartype interactive_message: ~azure.communication.messages.models.InteractiveMessage """ - kind: Literal[CommunicationMessageKind.INTERACTIVE] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.INTERACTIVE] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is Interactive. Required. Interactive Actionable message type.""" - interactive_message: "_models.InteractiveMessage" = rest_field(name="interactiveMessage") + interactive_message: "_models.InteractiveMessage" = rest_field( + name="interactiveMessage", visibility=["read", "create", "update", "delete", "query"] + ) """The interactive message content. Required.""" @overload @@ -638,8 +616,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class LinkContent(MessageContent, discriminator="url"): """The message content of type Url information. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is url. Required. The Url content type. :vartype kind: str or ~azure.communication.messages.models.URL :ivar title: Title of the url content. Required. @@ -648,11 +624,11 @@ class LinkContent(MessageContent, discriminator="url"): :vartype url: str """ - kind: Literal[MessageContentKind.URL] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.URL] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is url. Required. The Url content type.""" - title: str = rest_field() + title: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Title of the url content. Required.""" - url: str = rest_field() + url: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The url in the content. Required.""" @overload @@ -677,8 +653,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MediaNotificationContent(NotificationContent, discriminator="image_v0"): """@deprecated A request to send an image notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -694,12 +668,12 @@ class MediaNotificationContent(NotificationContent, discriminator="image_v0"): :vartype media_uri: str """ - kind: Literal[CommunicationMessageKind.IMAGE_V0] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.IMAGE_V0] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is image. Required. Image message type. Legacy image type for ``MediaNotificationContent`` which is being deprecated""" - content: Optional[str] = rest_field() + content: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Optional text content.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """A media url for the file. Required if the type is one of the supported media types, e.g. image. Required.""" @@ -727,16 +701,15 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageReceipt(_model_base.Model): """Receipt of the sending one message. - :ivar message_id: The message id. Required. :vartype message_id: str :ivar to: The native external platform user identifier of the recipient. Required. :vartype to: str """ - message_id: str = rest_field(name="messageId") + message_id: str = rest_field(name="messageId", visibility=["read", "create", "update", "delete", "query"]) """The message id. Required.""" - to: str = rest_field() + to: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The native external platform user identifier of the recipient. Required.""" @overload @@ -761,8 +734,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplate(_model_base.Model): """The template object used to create templates. - All required parameters must be populated in order to send to server. - :ivar name: Name of the template. Required. :vartype name: str :ivar language: The template's language, in the ISO 639 format, consist of a two-letter @@ -774,14 +745,18 @@ class MessageTemplate(_model_base.Model): :vartype bindings: ~azure.communication.messages.models.MessageTemplateBindings """ - name: str = rest_field() + name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Name of the template. Required.""" - language: str = rest_field() + language: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The template's language, in the ISO 639 format, consist of a two-letter language code followed by an optional two-letter country code, e.g., 'en' or 'en_US'. Required.""" - template_values: Optional[List["_models.MessageTemplateValue"]] = rest_field(name="values") + template_values: Optional[List["_models.MessageTemplateValue"]] = rest_field( + name="values", visibility=["read", "create", "update", "delete", "query"] + ) """The template values.""" - bindings: Optional["_models.MessageTemplateBindings"] = rest_field() + bindings: Optional["_models.MessageTemplateBindings"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The binding object to link values to the template specific locations.""" @overload @@ -811,14 +786,12 @@ class MessageTemplateBindings(_model_base.Model): You probably want to use the sub-classes and not this class directly. Known sub-classes are: WhatsAppMessageTemplateBindings - All required parameters must be populated in order to send to server. - :ivar kind: The type discriminator describing a template bindings type. Required. "whatsApp" :vartype kind: str or ~azure.communication.messages.models.MessageTemplateBindingsKind """ __mapping__: Dict[str, _model_base.Model] = {} - kind: str = rest_discriminator(name="kind") + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) """The type discriminator describing a template bindings type. Required. \"whatsApp\"""" @overload @@ -846,8 +819,6 @@ class MessageTemplateValue(_model_base.Model): MessageTemplateDocument, MessageTemplateImage, MessageTemplateLocation, MessageTemplateQuickAction, MessageTemplateText, MessageTemplateVideo - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: The type discriminator describing a template parameter type. Required. Known values @@ -856,9 +827,9 @@ class MessageTemplateValue(_model_base.Model): """ __mapping__: Dict[str, _model_base.Model] = {} - name: str = rest_field() + name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Template binding reference name. Required.""" - kind: str = rest_discriminator(name="kind") + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) """The type discriminator describing a template parameter type. Required. Known values are: \"text\", \"image\", \"document\", \"video\", \"location\", and \"quickAction\".""" @@ -884,8 +855,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplateDocument(MessageTemplateValue, discriminator="document"): """The message template's document value information. - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: Message parameter type is document. Required. The document template parameter type. @@ -898,13 +867,13 @@ class MessageTemplateDocument(MessageTemplateValue, discriminator="document"): :vartype file_name: str """ - kind: Literal[MessageTemplateValueKind.DOCUMENT] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateValueKind.DOCUMENT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message parameter type is document. Required. The document template parameter type.""" - url: str = rest_field() + url: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The (public) URL of the media. Required.""" - caption: Optional[str] = rest_field() + caption: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The [optional] caption of the media object.""" - file_name: Optional[str] = rest_field(name="fileName") + file_name: Optional[str] = rest_field(name="fileName", visibility=["read", "create", "update", "delete", "query"]) """The [optional] filename of the media file.""" @overload @@ -931,8 +900,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplateImage(MessageTemplateValue, discriminator="image"): """The message template's image value information. - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: Message parameter type is image. Required. The image template parameter type. @@ -945,13 +912,13 @@ class MessageTemplateImage(MessageTemplateValue, discriminator="image"): :vartype file_name: str """ - kind: Literal[MessageTemplateValueKind.IMAGE] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateValueKind.IMAGE] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message parameter type is image. Required. The image template parameter type.""" - url: str = rest_field() + url: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The (public) URL of the media. Required.""" - caption: Optional[str] = rest_field() + caption: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The [optional] caption of the media object.""" - file_name: Optional[str] = rest_field(name="fileName") + file_name: Optional[str] = rest_field(name="fileName", visibility=["read", "create", "update", "delete", "query"]) """The [optional] filename of the media file.""" @overload @@ -981,9 +948,6 @@ class MessageTemplateItem(_model_base.Model): You probably want to use the sub-classes and not this class directly. Known sub-classes are: WhatsAppMessageTemplateItem - Readonly variables are only populated by the server, and will be ignored when sending a request. - - :ivar name: The template's name. Required. :vartype name: str :ivar language: The template's language, in the ISO 639 format, consist of a two-letter @@ -999,13 +963,15 @@ class MessageTemplateItem(_model_base.Model): __mapping__: Dict[str, _model_base.Model] = {} name: str = rest_field(visibility=["read"]) """The template's name. Required.""" - language: str = rest_field() + language: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The template's language, in the ISO 639 format, consist of a two-letter language code followed by an optional two-letter country code, e.g., 'en' or 'en_US'. Required.""" - status: Union[str, "_models.MessageTemplateStatus"] = rest_field() + status: Union[str, "_models.MessageTemplateStatus"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The aggregated template status. Required. Known values are: \"approved\", \"rejected\", \"pending\", and \"paused\".""" - kind: str = rest_discriminator(name="kind") + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) """The type discriminator describing a template type. Required. \"whatsApp\"""" @overload @@ -1031,8 +997,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplateLocation(MessageTemplateValue, discriminator="location"): """The message template's location value information. - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: Message parameter type is location. Required. The location template parameter type. @@ -1047,15 +1011,17 @@ class MessageTemplateLocation(MessageTemplateValue, discriminator="location"): :vartype longitude: float """ - kind: Literal[MessageTemplateValueKind.LOCATION] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateValueKind.LOCATION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message parameter type is location. Required. The location template parameter type.""" - location_name: Optional[str] = rest_field(name="locationName") + location_name: Optional[str] = rest_field( + name="locationName", visibility=["read", "create", "update", "delete", "query"] + ) """The [Optional] name of the location.""" - address: Optional[str] = rest_field() + address: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The [Optional] address of the location.""" - latitude: float = rest_field() + latitude: float = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The latitude of the location. Required.""" - longitude: float = rest_field() + longitude: float = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The longitude of the location. Required.""" @overload @@ -1083,8 +1049,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplateQuickAction(MessageTemplateValue, discriminator="quickAction"): """The message template's quick action value information. - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: Message parameter type is quick action. Required. The quick action template @@ -1096,11 +1060,11 @@ class MessageTemplateQuickAction(MessageTemplateValue, discriminator="quickActio :vartype payload: str """ - kind: Literal[MessageTemplateValueKind.QUICK_ACTION] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateValueKind.QUICK_ACTION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message parameter type is quick action. Required. The quick action template parameter type.""" - text: Optional[str] = rest_field() + text: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The [Optional] quick action text.""" - payload: Optional[str] = rest_field() + payload: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The [Optional] quick action payload.""" @overload @@ -1126,8 +1090,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplateText(MessageTemplateValue, discriminator="text"): """The message template's text value information. - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: Message parameter type is text. Required. The text template parameter type. @@ -1136,9 +1098,9 @@ class MessageTemplateText(MessageTemplateValue, discriminator="text"): :vartype text: str """ - kind: Literal[MessageTemplateValueKind.TEXT] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateValueKind.TEXT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message parameter type is text. Required. The text template parameter type.""" - text: str = rest_field() + text: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The text value. Required.""" @overload @@ -1163,8 +1125,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplateVideo(MessageTemplateValue, discriminator="video"): """The message template's video value information. - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: Message parameter type is video. Required. The video template parameter type. @@ -1177,13 +1137,13 @@ class MessageTemplateVideo(MessageTemplateValue, discriminator="video"): :vartype file_name: str """ - kind: Literal[MessageTemplateValueKind.VIDEO] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateValueKind.VIDEO] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message parameter type is video. Required. The video template parameter type.""" - url: str = rest_field() + url: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The (public) URL of the media. Required.""" - caption: Optional[str] = rest_field() + caption: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The [optional] caption of the media object.""" - file_name: Optional[str] = rest_field(name="fileName") + file_name: Optional[str] = rest_field(name="fileName", visibility=["read", "create", "update", "delete", "query"]) """The [optional] filename of the media file.""" @overload @@ -1210,8 +1170,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ReactionNotificationContent(NotificationContent, discriminator="reaction"): """A request to send a Reaction notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -1219,17 +1177,17 @@ class ReactionNotificationContent(NotificationContent, discriminator="reaction") :vartype to: list[str] :ivar kind: Message notification type is reaction. Required. Reaction message type. :vartype kind: str or ~azure.communication.messages.models.REACTION - :ivar emoji: emoji content like uD83D. Required. + :ivar emoji: emoji content like \\uD83D\\uDE00. Required. :vartype emoji: str :ivar message_id: ID of the previous message you want to reply to. Required. :vartype message_id: str """ - kind: Literal[CommunicationMessageKind.REACTION] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.REACTION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is reaction. Required. Reaction message type.""" - emoji: str = rest_field() - """emoji content like :) Required.""" - message_id: str = rest_field(name="messageId") + emoji: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """emoji content like \uD83D\uDE00. Required.""" + message_id: str = rest_field(name="messageId", visibility=["read", "create", "update", "delete", "query"]) """ID of the previous message you want to reply to. Required.""" @overload @@ -1256,12 +1214,11 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class SendMessageResult(_model_base.Model): """Result of the send message operation. - :ivar receipts: Receipts of the send message operation. Required. :vartype receipts: list[~azure.communication.messages.models.MessageReceipt] """ - receipts: List["_models.MessageReceipt"] = rest_field() + receipts: List["_models.MessageReceipt"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Receipts of the send message operation. Required.""" @overload @@ -1285,8 +1242,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class StickerNotificationContent(NotificationContent, discriminator="sticker"): """A request to send a Sticker notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -1299,9 +1254,9 @@ class StickerNotificationContent(NotificationContent, discriminator="sticker"): :vartype media_uri: str """ - kind: Literal[CommunicationMessageKind.STICKER] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.STICKER] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is sticker. Required. Sticker message type.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """A media url for the file. Required if the type is one of the supported media types, e.g. image. Required.""" @@ -1328,8 +1283,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class TemplateNotificationContent(NotificationContent, discriminator="template"): """A request to send a template notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -1341,9 +1294,9 @@ class TemplateNotificationContent(NotificationContent, discriminator="template") :vartype template: ~azure.communication.messages.models.MessageTemplate """ - kind: Literal[CommunicationMessageKind.TEMPLATE] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.TEMPLATE] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is template. Required. Template message type.""" - template: "_models.MessageTemplate" = rest_field() + template: "_models.MessageTemplate" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The template object used to create templates. Required.""" @overload @@ -1369,17 +1322,15 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class TextMessageContent(MessageContent, discriminator="text"): """The message content of type text information. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is text. Required. The text content type. :vartype kind: str or ~azure.communication.messages.models.TEXT :ivar text: The text value. Required. :vartype text: str """ - kind: Literal[MessageContentKind.TEXT] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.TEXT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is text. Required. The text content type.""" - text: str = rest_field() + text: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The text value. Required.""" @overload @@ -1403,8 +1354,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class TextNotificationContent(NotificationContent, discriminator="text"): """A request to send a text notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -1416,9 +1365,9 @@ class TextNotificationContent(NotificationContent, discriminator="text"): :vartype content: str """ - kind: Literal[CommunicationMessageKind.TEXT] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.TEXT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is text. Required. Text message type.""" - content: str = rest_field() + content: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Message content. Required.""" @overload @@ -1444,17 +1393,15 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class VideoMessageContent(MessageContent, discriminator="video"): """The message content of type video information. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is video. Required. The video content type. :vartype kind: str or ~azure.communication.messages.models.VIDEO :ivar media_uri: MediaUri of the media content. Required. :vartype media_uri: str """ - kind: Literal[MessageContentKind.VIDEO] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.VIDEO] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is video. Required. The video content type.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """MediaUri of the media content. Required.""" @overload @@ -1478,8 +1425,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class VideoNotificationContent(NotificationContent, discriminator="video"): """A request to send a video notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -1494,11 +1439,11 @@ class VideoNotificationContent(NotificationContent, discriminator="video"): :vartype media_uri: str """ - kind: Literal[CommunicationMessageKind.VIDEO] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.VIDEO] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is image. Required. Video message type.""" - caption: Optional[str] = rest_field() + caption: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Optional text content.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """A media url for the file. Required if the type is one of the supported media types, e.g. image. Required.""" @@ -1526,8 +1471,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class WhatsAppButtonActionBindings(ActionBindings, discriminator="whatsAppButtonAction"): """WhatsApp Binding actions to the interactive message. - All required parameters must be populated in order to send to server. - :ivar kind: Message action binding type is WhatsAppButtonAction. Required. The WhatsApp Button action binding kind. :vartype kind: str or ~azure.communication.messages.models.WHATS_APP_BUTTON_ACTION @@ -1535,10 +1478,10 @@ class WhatsAppButtonActionBindings(ActionBindings, discriminator="whatsAppButton :vartype content: ~azure.communication.messages.models.ButtonSetContent """ - kind: Literal[MessageActionBindingKind.WHATS_APP_BUTTON_ACTION] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageActionBindingKind.WHATS_APP_BUTTON_ACTION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message action binding type is WhatsAppButtonAction. Required. The WhatsApp Button action binding kind.""" - content: "_models.ButtonSetContent" = rest_field() + content: "_models.ButtonSetContent" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Action content of Interactive message. Required.""" @overload @@ -1562,8 +1505,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class WhatsAppListActionBindings(ActionBindings, discriminator="whatsAppListAction"): """WhatsApp List Binding actions to the interactive message. - All required parameters must be populated in order to send to server. - :ivar kind: Message action binding type is WhatsAppListAction. Required. The WhatsApp List action binding kind. :vartype kind: str or ~azure.communication.messages.models.WHATS_APP_LIST_ACTION @@ -1571,10 +1512,10 @@ class WhatsAppListActionBindings(ActionBindings, discriminator="whatsAppListActi :vartype content: ~azure.communication.messages.models.ActionGroupContent """ - kind: Literal[MessageActionBindingKind.WHATS_APP_LIST_ACTION] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageActionBindingKind.WHATS_APP_LIST_ACTION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message action binding type is WhatsAppListAction. Required. The WhatsApp List action binding kind.""" - content: "_models.ActionGroupContent" = rest_field() + content: "_models.ActionGroupContent" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Action content of Interactive message. Required.""" @overload @@ -1598,10 +1539,8 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class WhatsAppMessageTemplateBindings(MessageTemplateBindings, discriminator="whatsApp"): """The template bindings for WhatsApp. - All required parameters must be populated in order to send to server. - :ivar kind: MessageTemplateBindings is whatsApp. Required. The WhatsApp template type. - :vartype kind: str or ~azure.communication.messages.models.WHATSAPP + :vartype kind: str or ~azure.communication.messages.models.WHATS_APP :ivar header: The header template bindings. :vartype header: list[~azure.communication.messages.models.WhatsAppMessageTemplateBindingsComponent] @@ -1616,15 +1555,23 @@ class WhatsAppMessageTemplateBindings(MessageTemplateBindings, discriminator="wh list[~azure.communication.messages.models.WhatsAppMessageTemplateBindingsButton] """ - kind: Literal[MessageTemplateBindingsKind.WHATSAPP] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateBindingsKind.WHATS_APP] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """MessageTemplateBindings is whatsApp. Required. The WhatsApp template type.""" - header: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = rest_field() + header: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The header template bindings.""" - body: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = rest_field() + body: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The body template bindings.""" - footer: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = rest_field() + footer: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The footer template bindings.""" - buttons: Optional[List["_models.WhatsAppMessageTemplateBindingsButton"]] = rest_field() + buttons: Optional[List["_models.WhatsAppMessageTemplateBindingsButton"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The button template bindings.""" @overload @@ -1645,14 +1592,12 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: """ def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, kind=MessageTemplateBindingsKind.WHATSAPP, **kwargs) + super().__init__(*args, kind=MessageTemplateBindingsKind.WHATS_APP, **kwargs) class WhatsAppMessageTemplateBindingsButton(_model_base.Model): """The template bindings component button for WhatsApp. - All required parameters must be populated in order to send to server. - :ivar sub_type: The WhatsApp button sub type. Required. Known values are: "quickReply" and "url". :vartype sub_type: str or ~azure.communication.messages.models.WhatsAppMessageButtonSubType @@ -1660,9 +1605,11 @@ class WhatsAppMessageTemplateBindingsButton(_model_base.Model): :vartype ref_value: str """ - sub_type: Union[str, "_models.WhatsAppMessageButtonSubType"] = rest_field(name="subType") + sub_type: Union[str, "_models.WhatsAppMessageButtonSubType"] = rest_field( + name="subType", visibility=["read", "create", "update", "delete", "query"] + ) """The WhatsApp button sub type. Required. Known values are: \"quickReply\" and \"url\".""" - ref_value: str = rest_field(name="refValue") + ref_value: str = rest_field(name="refValue", visibility=["read", "create", "update", "delete", "query"]) """The name of the referenced item in the template values. Required.""" @overload @@ -1687,13 +1634,11 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class WhatsAppMessageTemplateBindingsComponent(_model_base.Model): """The template bindings component for WhatsApp. - All required parameters must be populated in order to send to server. - :ivar ref_value: The name of the referenced item in the template values. Required. :vartype ref_value: str """ - ref_value: str = rest_field(name="refValue") + ref_value: str = rest_field(name="refValue", visibility=["read", "create", "update", "delete", "query"]) """The name of the referenced item in the template values. Required.""" @overload @@ -1717,9 +1662,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class WhatsAppMessageTemplateItem(MessageTemplateItem, discriminator="whatsApp"): """The WhatsApp-specific template response contract. - Readonly variables are only populated by the server, and will be ignored when sending a request. - - :ivar name: The template's name. Required. :vartype name: str :ivar language: The template's language, in the ISO 639 format, consist of a two-letter @@ -1733,12 +1675,12 @@ class WhatsAppMessageTemplateItem(MessageTemplateItem, discriminator="whatsApp") :vartype content: any :ivar kind: Message template response type is whatsApp. Required. The WhatsApp communication messages channel type. - :vartype kind: str or ~azure.communication.messages.models.WHATSAPP + :vartype kind: str or ~azure.communication.messages.models.WHATS_APP """ - content: Optional[Any] = rest_field() + content: Optional[Any] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """WhatsApp platform's template content. This is the payload returned from WhatsApp API.""" - kind: Literal[CommunicationMessagesChannel.WHATSAPP] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessagesChannel.WHATS_APP] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message template response type is whatsApp. Required. The WhatsApp communication messages channel type.""" @@ -1759,14 +1701,12 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: """ def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, kind=CommunicationMessagesChannel.WHATSAPP, **kwargs) + super().__init__(*args, kind=CommunicationMessagesChannel.WHATS_APP, **kwargs) class WhatsAppUrlActionBindings(ActionBindings, discriminator="whatsAppUrlAction"): """WhatsApp Binding actions to the interactive message. - All required parameters must be populated in order to send to server. - :ivar kind: Message action binding type is WhatsAppUrlAction. Required. The WhatsApp Url action binding kind. :vartype kind: str or ~azure.communication.messages.models.WHATS_APP_URL_ACTION @@ -1774,10 +1714,10 @@ class WhatsAppUrlActionBindings(ActionBindings, discriminator="whatsAppUrlAction :vartype content: ~azure.communication.messages.models.LinkContent """ - kind: Literal[MessageActionBindingKind.WHATS_APP_URL_ACTION] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageActionBindingKind.WHATS_APP_URL_ACTION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message action binding type is WhatsAppUrlAction. Required. The WhatsApp Url action binding kind.""" - content: "_models.LinkContent" = rest_field() + content: "_models.LinkContent" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Action content of Interactive message. Required.""" @overload diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/models/_patch.py b/sdk/communication/azure-communication-messages/azure/communication/messages/models/_patch.py index f7dd32510333..8bcb627aa475 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/models/_patch.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/models/_patch.py @@ -1,7 +1,8 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------- """Customize generated code here. Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize diff --git a/sdk/communication/azure-communication-messages/generated_samples/stream_get_media.py b/sdk/communication/azure-communication-messages/generated_samples/stream_get_media.py new file mode 100644 index 000000000000..cb254d8bf688 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_samples/stream_get_media.py @@ -0,0 +1,33 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from azure.communication.messages import NotificationMessagesClient + +""" +# PREREQUISITES + pip install azure-communication-messages +# USAGE + python stream_get_media.py +""" + + +def main(): + client = NotificationMessagesClient( + endpoint="https://my-resource.communication.azure.com", + credential="CREDENTIAL", + ) + + response = client.download_media( + id="d19e68ec-bdd6-4a50-8dfb-cbb1642df6ab", + ) + print(response) + + +# x-ms-original-file: 2025-01-15-preview/Stream_GetMedia.json +if __name__ == "__main__": + main() diff --git a/sdk/communication/azure-communication-messages/generated_tests/conftest.py b/sdk/communication/azure-communication-messages/generated_tests/conftest.py new file mode 100644 index 000000000000..381df64efbf4 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/conftest.py @@ -0,0 +1,58 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import os +import pytest +from dotenv import load_dotenv +from devtools_testutils import ( + test_proxy, + add_general_regex_sanitizer, + add_body_key_sanitizer, + add_header_regex_sanitizer, +) + +load_dotenv() + + +# For security, please avoid record sensitive identity information in recordings +@pytest.fixture(scope="session", autouse=True) +def add_sanitizers(test_proxy): + notificationmessages_subscription_id = os.environ.get( + "NOTIFICATIONMESSAGES_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000" + ) + notificationmessages_tenant_id = os.environ.get( + "NOTIFICATIONMESSAGES_TENANT_ID", "00000000-0000-0000-0000-000000000000" + ) + notificationmessages_client_id = os.environ.get( + "NOTIFICATIONMESSAGES_CLIENT_ID", "00000000-0000-0000-0000-000000000000" + ) + notificationmessages_client_secret = os.environ.get( + "NOTIFICATIONMESSAGES_CLIENT_SECRET", "00000000-0000-0000-0000-000000000000" + ) + add_general_regex_sanitizer( + regex=notificationmessages_subscription_id, value="00000000-0000-0000-0000-000000000000" + ) + add_general_regex_sanitizer(regex=notificationmessages_tenant_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=notificationmessages_client_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=notificationmessages_client_secret, value="00000000-0000-0000-0000-000000000000") + + messagetemplate_subscription_id = os.environ.get( + "MESSAGETEMPLATE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000" + ) + messagetemplate_tenant_id = os.environ.get("MESSAGETEMPLATE_TENANT_ID", "00000000-0000-0000-0000-000000000000") + messagetemplate_client_id = os.environ.get("MESSAGETEMPLATE_CLIENT_ID", "00000000-0000-0000-0000-000000000000") + messagetemplate_client_secret = os.environ.get( + "MESSAGETEMPLATE_CLIENT_SECRET", "00000000-0000-0000-0000-000000000000" + ) + add_general_regex_sanitizer(regex=messagetemplate_subscription_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=messagetemplate_tenant_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=messagetemplate_client_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=messagetemplate_client_secret, value="00000000-0000-0000-0000-000000000000") + + add_header_regex_sanitizer(key="Set-Cookie", value="[set-cookie;]") + add_header_regex_sanitizer(key="Cookie", value="cookie;") + add_body_key_sanitizer(json_path="$..access_token", value="access_token") diff --git a/sdk/communication/azure-communication-messages/generated_tests/test_message_template.py b/sdk/communication/azure-communication-messages/generated_tests/test_message_template.py new file mode 100644 index 000000000000..dabf704a6444 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/test_message_template.py @@ -0,0 +1,24 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import pytest +from devtools_testutils import recorded_by_proxy +from testpreparer import MessageTemplateClientTestBase, MessageTemplatePreparer + + +@pytest.mark.skip("you may need to update the auto-generated test case before run it") +class TestMessageTemplate(MessageTemplateClientTestBase): + @MessageTemplatePreparer() + @recorded_by_proxy + def test_list_templates(self, messagetemplate_endpoint): + client = self.create_client(endpoint=messagetemplate_endpoint) + response = client.list_templates( + channel_id="str", + ) + result = [r for r in response] + # please add some check logic here by yourself + # ... diff --git a/sdk/communication/azure-communication-messages/generated_tests/test_message_template_async.py b/sdk/communication/azure-communication-messages/generated_tests/test_message_template_async.py new file mode 100644 index 000000000000..17dc315792dd --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/test_message_template_async.py @@ -0,0 +1,25 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import pytest +from devtools_testutils.aio import recorded_by_proxy_async +from testpreparer import MessageTemplatePreparer +from testpreparer_async import MessageTemplateClientTestBaseAsync + + +@pytest.mark.skip("you may need to update the auto-generated test case before run it") +class TestMessageTemplateAsync(MessageTemplateClientTestBaseAsync): + @MessageTemplatePreparer() + @recorded_by_proxy_async + async def test_list_templates(self, messagetemplate_endpoint): + client = self.create_async_client(endpoint=messagetemplate_endpoint) + response = client.list_templates( + channel_id="str", + ) + result = [r async for r in response] + # please add some check logic here by yourself + # ... diff --git a/sdk/communication/azure-communication-messages/generated_tests/test_notification_messages.py b/sdk/communication/azure-communication-messages/generated_tests/test_notification_messages.py new file mode 100644 index 000000000000..23071ca986e6 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/test_notification_messages.py @@ -0,0 +1,35 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import pytest +from devtools_testutils import recorded_by_proxy +from testpreparer import NotificationMessagesClientTestBase, NotificationMessagesPreparer + + +@pytest.mark.skip("you may need to update the auto-generated test case before run it") +class TestNotificationMessages(NotificationMessagesClientTestBase): + @NotificationMessagesPreparer() + @recorded_by_proxy + def test_send(self, notificationmessages_endpoint): + client = self.create_client(endpoint=notificationmessages_endpoint) + response = client.send( + body={"channelRegistrationId": "str", "kind": "audio", "mediaUri": "str", "to": ["str"]}, + ) + + # please add some check logic here by yourself + # ... + + @NotificationMessagesPreparer() + @recorded_by_proxy + def test_download_media(self, notificationmessages_endpoint): + client = self.create_client(endpoint=notificationmessages_endpoint) + response = client.download_media( + id="str", + ) + + # please add some check logic here by yourself + # ... diff --git a/sdk/communication/azure-communication-messages/generated_tests/test_notification_messages_async.py b/sdk/communication/azure-communication-messages/generated_tests/test_notification_messages_async.py new file mode 100644 index 000000000000..27188dc4eb4d --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/test_notification_messages_async.py @@ -0,0 +1,36 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import pytest +from devtools_testutils.aio import recorded_by_proxy_async +from testpreparer import NotificationMessagesPreparer +from testpreparer_async import NotificationMessagesClientTestBaseAsync + + +@pytest.mark.skip("you may need to update the auto-generated test case before run it") +class TestNotificationMessagesAsync(NotificationMessagesClientTestBaseAsync): + @NotificationMessagesPreparer() + @recorded_by_proxy_async + async def test_send(self, notificationmessages_endpoint): + client = self.create_async_client(endpoint=notificationmessages_endpoint) + response = await client.send( + body={"channelRegistrationId": "str", "kind": "audio", "mediaUri": "str", "to": ["str"]}, + ) + + # please add some check logic here by yourself + # ... + + @NotificationMessagesPreparer() + @recorded_by_proxy_async + async def test_download_media(self, notificationmessages_endpoint): + client = self.create_async_client(endpoint=notificationmessages_endpoint) + response = await client.download_media( + id="str", + ) + + # please add some check logic here by yourself + # ... diff --git a/sdk/communication/azure-communication-messages/generated_tests/testpreparer.py b/sdk/communication/azure-communication-messages/generated_tests/testpreparer.py new file mode 100644 index 000000000000..b7641dca06e4 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/testpreparer.py @@ -0,0 +1,44 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from azure.communication.messages import MessageTemplateClient, NotificationMessagesClient +from devtools_testutils import AzureRecordedTestCase, PowerShellPreparer +import functools + + +class NotificationMessagesClientTestBase(AzureRecordedTestCase): + + def create_client(self, endpoint): + credential = self.get_credential(NotificationMessagesClient) + return self.create_client_from_credential( + NotificationMessagesClient, + credential=credential, + endpoint=endpoint, + ) + + +NotificationMessagesPreparer = functools.partial( + PowerShellPreparer, + "notificationmessages", + notificationmessages_endpoint="https://fake_notificationmessages_endpoint.com", +) + + +class MessageTemplateClientTestBase(AzureRecordedTestCase): + + def create_client(self, endpoint): + credential = self.get_credential(MessageTemplateClient) + return self.create_client_from_credential( + MessageTemplateClient, + credential=credential, + endpoint=endpoint, + ) + + +MessageTemplatePreparer = functools.partial( + PowerShellPreparer, "messagetemplate", messagetemplate_endpoint="https://fake_messagetemplate_endpoint.com" +) diff --git a/sdk/communication/azure-communication-messages/generated_tests/testpreparer_async.py b/sdk/communication/azure-communication-messages/generated_tests/testpreparer_async.py new file mode 100644 index 000000000000..ffa7ee49f930 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/testpreparer_async.py @@ -0,0 +1,31 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from azure.communication.messages.aio import MessageTemplateClient, NotificationMessagesClient +from devtools_testutils import AzureRecordedTestCase + + +class NotificationMessagesClientTestBaseAsync(AzureRecordedTestCase): + + def create_async_client(self, endpoint): + credential = self.get_credential(NotificationMessagesClient, is_async=True) + return self.create_client_from_credential( + NotificationMessagesClient, + credential=credential, + endpoint=endpoint, + ) + + +class MessageTemplateClientTestBaseAsync(AzureRecordedTestCase): + + def create_async_client(self, endpoint): + credential = self.get_credential(MessageTemplateClient, is_async=True) + return self.create_client_from_credential( + MessageTemplateClient, + credential=credential, + endpoint=endpoint, + ) diff --git a/sdk/communication/azure-communication-messages/samples/download_media.py b/sdk/communication/azure-communication-messages/samples/download_media.py index ad965cfd1039..a67fd9c37280 100644 --- a/sdk/communication/azure-communication-messages/samples/download_media.py +++ b/sdk/communication/azure-communication-messages/samples/download_media.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/get_templates_list.py b/sdk/communication/azure-communication-messages/samples/get_templates_list.py index 91e6a1c76abc..e05ec4442928 100644 --- a/sdk/communication/azure-communication-messages/samples/get_templates_list.py +++ b/sdk/communication/azure-communication-messages/samples/get_templates_list.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/get_templates_list_async.py b/sdk/communication/azure-communication-messages/samples/get_templates_list_async.py index 261767c07d80..6c7ccb98af37 100644 --- a/sdk/communication/azure-communication-messages/samples/get_templates_list_async.py +++ b/sdk/communication/azure-communication-messages/samples/get_templates_list_async.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_audio_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_audio_notification_messages.py index 7c4f11c55082..61bb5ecabc9f 100644 --- a/sdk/communication/azure-communication-messages/samples/send_audio_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_audio_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_document_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_document_notification_messages.py index 847a8d2a08fb..80f52de212d3 100644 --- a/sdk/communication/azure-communication-messages/samples/send_document_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_document_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_image_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_image_notification_messages.py index dcf813287188..fac960e33c89 100644 --- a/sdk/communication/azure-communication-messages/samples/send_image_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_image_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_image_notification_messages_async.py b/sdk/communication/azure-communication-messages/samples/send_image_notification_messages_async.py index df8f4a72e18f..ec61fdcd4ddc 100644 --- a/sdk/communication/azure-communication-messages/samples/send_image_notification_messages_async.py +++ b/sdk/communication/azure-communication-messages/samples/send_image_notification_messages_async.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_reaction_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_reaction_notification_messages.py index 91d49adda406..22ba1751ee91 100644 --- a/sdk/communication/azure-communication-messages/samples/send_reaction_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_reaction_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_sticker_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_sticker_notification_messages.py index d72c41bab74e..aac9efdc28ef 100644 --- a/sdk/communication/azure-communication-messages/samples/send_sticker_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_sticker_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_template_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_template_notification_messages.py index 8887e73c6744..eb9b990eca97 100644 --- a/sdk/communication/azure-communication-messages/samples/send_template_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_template_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_template_notification_messages_async.py b/sdk/communication/azure-communication-messages/samples/send_template_notification_messages_async.py index d3d2d4d26874..3ccc0f388875 100644 --- a/sdk/communication/azure-communication-messages/samples/send_template_notification_messages_async.py +++ b/sdk/communication/azure-communication-messages/samples/send_template_notification_messages_async.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_text_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_text_notification_messages.py index 390ae2f5d28b..051afe425883 100644 --- a/sdk/communication/azure-communication-messages/samples/send_text_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_text_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_async.py b/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_async.py index 5b7cdfe4d88d..fdba46a3cd3a 100644 --- a/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_async.py +++ b/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_async.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_with_token_credentials.py b/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_with_token_credentials.py index 55d28e259269..df67174d0299 100644 --- a/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_with_token_credentials.py +++ b/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_with_token_credentials.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_video_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_video_notification_messages.py index 96d697ac81db..7d1d4ebbf316 100644 --- a/sdk/communication/azure-communication-messages/samples/send_video_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_video_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_whatsapp_list_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_whatsapp_list_notification_messages.py index 2407f0d09504..0a6df4e72ec8 100644 --- a/sdk/communication/azure-communication-messages/samples/send_whatsapp_list_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_whatsapp_list_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_whatsapp_urlbased_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_whatsapp_urlbased_notification_messages.py index 8af8358be64b..e73227267a05 100644 --- a/sdk/communication/azure-communication-messages/samples/send_whatsapp_urlbased_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_whatsapp_urlbased_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_whatsappreplybutton_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_whatsappreplybutton_notification_messages.py index 06634802466a..976bef5a072d 100644 --- a/sdk/communication/azure-communication-messages/samples/send_whatsappreplybutton_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_whatsappreplybutton_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/setup.py b/sdk/communication/azure-communication-messages/setup.py index c0d6b48794c6..a966485d096c 100644 --- a/sdk/communication/azure-communication-messages/setup.py +++ b/sdk/communication/azure-communication-messages/setup.py @@ -5,7 +5,7 @@ # Code generated by Microsoft (R) Python Code Generator. # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -# coding: utf-8 + import os import re @@ -29,7 +29,7 @@ setup( name=PACKAGE_NAME, version=version, - description="Microsoft {} Client Library for Python".format(PACKAGE_PPRINT_NAME), + description="Microsoft Corporation {} Client Library for Python".format(PACKAGE_PPRINT_NAME), long_description=open("README.md", "r").read(), long_description_content_type="text/markdown", license="MIT License", diff --git a/sdk/communication/azure-communication-messages/tests/_shared/communication_service_preparer.py b/sdk/communication/azure-communication-messages/tests/_shared/communication_service_preparer.py index 2502a4713a88..e552ff83a69a 100644 --- a/sdk/communication/azure-communication-messages/tests/_shared/communication_service_preparer.py +++ b/sdk/communication/azure-communication-messages/tests/_shared/communication_service_preparer.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # ------------------------------------ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. diff --git a/sdk/communication/azure-communication-messages/tsp-location.yaml b/sdk/communication/azure-communication-messages/tsp-location.yaml index b6a10b5b40ee..53b011b13cec 100644 --- a/sdk/communication/azure-communication-messages/tsp-location.yaml +++ b/sdk/communication/azure-communication-messages/tsp-location.yaml @@ -1,4 +1,4 @@ directory: specification/communication/Communication.Messages -commit: 7797d20dce4f18ee2b3709b894f22634d6fb8b1e +commit: 5b8b9e16f73291ccad4972febd28ca32ff908cd1 repo: Azure/azure-rest-api-specs -additionalDirectories: [] +additionalDirectories: