diff --git a/sdk/communication/azure-communication-messages/CHANGELOG.md b/sdk/communication/azure-communication-messages/CHANGELOG.md
index 4a0cc3c8b81c..1ff25f482e45 100644
--- a/sdk/communication/azure-communication-messages/CHANGELOG.md
+++ b/sdk/communication/azure-communication-messages/CHANGELOG.md
@@ -1,14 +1,13 @@
# Release History
-## 1.0.1 (Unreleased)
+## 1.1.0 (2024-10-25)
+This is feature addition release.
### Features Added
-
-### Breaking Changes
-
-### Bugs Fixed
-
-### Other Changes
+- Using `NotificationMessagesClient`
+ - Send Video messages
+ - Send Audio messages
+ - Send Document messages
## 1.0.0 (2024-03-25)
@@ -18,7 +17,7 @@ This is the GA release of Azure Communication Messages Python SDK. For more info
- Using `NotificationMessagesClient`
- Send Text messages
- Send Template messages
- - Send Media messages
+ - Send Image messages
- Using `MessageTemplateClient`
- Get list of all WhatsApp templates.
diff --git a/sdk/communication/azure-communication-messages/assets.json b/sdk/communication/azure-communication-messages/assets.json
index 770b23e9293d..f4c8dabd60bf 100644
--- a/sdk/communication/azure-communication-messages/assets.json
+++ b/sdk/communication/azure-communication-messages/assets.json
@@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "python",
"TagPrefix": "python/communication/azure-communication-messages",
- "Tag": "python/communication/azure-communication-messages_22ab5a97f3"
+ "Tag": "python/communication/azure-communication-messages_302bf9560e"
}
diff --git a/sdk/communication/azure-communication-messages/azure/__init__.py b/sdk/communication/azure-communication-messages/azure/__init__.py
index 0d1f7edf5dc6..d55ccad1f573 100644
--- a/sdk/communication/azure-communication-messages/azure/__init__.py
+++ b/sdk/communication/azure-communication-messages/azure/__init__.py
@@ -1 +1 @@
-__path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore
+__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore
diff --git a/sdk/communication/azure-communication-messages/azure/communication/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/__init__.py
index 0d1f7edf5dc6..d55ccad1f573 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/__init__.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/__init__.py
@@ -1 +1 @@
-__path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore
+__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore
diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/messages/__init__.py
index 12815161d8d6..3ce4f906d3df 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/__init__.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/__init__.py
@@ -18,9 +18,10 @@
except ImportError:
_patch_all = []
from ._patch import patch_sdk as _patch_sdk
+
__all__ = [
- 'NotificationMessagesClient',
- 'MessageTemplateClient',
+ "NotificationMessagesClient",
+ "MessageTemplateClient",
]
__all__.extend([p for p in _patch_all if p not in __all__])
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
index 97f1f0cc4095..dd1c75a2a5a8 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/_api_versions.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_api_versions.py
@@ -10,6 +10,7 @@
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"
-DEFAULT_VERSION = ApiVersion.V2024_02_01.value
+DEFAULT_VERSION = ApiVersion.V2024_08_30.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 6007feaa0ca9..d86dd1c37d16 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/_client.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_client.py
@@ -8,6 +8,7 @@
from copy import deepcopy
from typing import Any, TYPE_CHECKING, Union
+from typing_extensions import Self
from azure.core import PipelineClient
from azure.core.credentials import AzureKeyCredential
@@ -22,53 +23,51 @@
# pylint: disable=unused-import,ungrouped-imports
from azure.core.credentials import TokenCredential
-class NotificationMessagesClient(NotificationMessagesClientOperationsMixin): # pylint: disable=client-accepts-api-version-keyword
+
+class NotificationMessagesClient(
+ NotificationMessagesClientOperationsMixin
+): # pylint: disable=client-accepts-api-version-keyword
"""NotificationMessagesClient.
:param endpoint: The communication resource, for example
https://my-resource.communication.azure.com. Required.
:type endpoint: str
- :param credential: Credential needed for the client to connect to Azure. Is either a
+ :param credential: Credential used to authenticate requests to the service. Is either a
TokenCredential type or a AzureKeyCredential 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 "2024-02-01".
+ :keyword api_version: The API version to use for this operation. Default value is "2024-08-30".
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:
- _endpoint = '{endpoint}'
+ def __init__(self, endpoint: str, credential: Union["TokenCredential", AzureKeyCredential], **kwargs: Any) -> None:
+ _endpoint = "{endpoint}"
self._config = NotificationMessagesClientConfiguration(endpoint=endpoint, credential=credential, **kwargs)
- _policies = kwargs.pop('policies', None)
+ _policies = kwargs.pop("policies", None)
if _policies is None:
- _policies = [policies.RequestIdPolicy(**kwargs),self._config.headers_policy,
- self._config.user_agent_policy,self._config.proxy_policy,
- policies.ContentDecodePolicy(**kwargs),
- self._config.redirect_policy,self._config.retry_policy,
- self._config.authentication_policy,
- self._config.custom_hook_policy,self._config.logging_policy,
- policies.DistributedTracingPolicy(**kwargs),
- policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None,
- self._config.http_logging_policy]
+ _policies = [
+ policies.RequestIdPolicy(**kwargs),
+ self._config.headers_policy,
+ self._config.user_agent_policy,
+ self._config.proxy_policy,
+ policies.ContentDecodePolicy(**kwargs),
+ self._config.redirect_policy,
+ self._config.retry_policy,
+ self._config.authentication_policy,
+ self._config.custom_hook_policy,
+ self._config.logging_policy,
+ policies.DistributedTracingPolicy(**kwargs),
+ policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None,
+ self._config.http_logging_policy,
+ ]
self._client: PipelineClient = PipelineClient(base_url=_endpoint, policies=_policies, **kwargs)
-
self._serialize = Serializer()
self._deserialize = Deserializer()
self._serialize.client_side_validation = False
-
- def send_request(
- self,
- request: HttpRequest, *, stream: bool = False,
- **kwargs: Any
- ) -> HttpResponse:
+ def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs: Any) -> HttpResponse:
"""Runs the network request through the client's chained policies.
>>> from azure.core.rest import HttpRequest
@@ -88,7 +87,7 @@ def send_request(
request_copy = deepcopy(request)
path_format_arguments = {
- "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, 'str', skip_quote=True),
+ "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
}
request_copy.url = self._client.format_url(request_copy.url, **path_format_arguments)
@@ -97,56 +96,56 @@ def send_request(
def close(self) -> None:
self._client.close()
- def __enter__(self) -> "NotificationMessagesClient":
+ def __enter__(self) -> Self:
self._client.__enter__()
return self
def __exit__(self, *exc_details: Any) -> None:
self._client.__exit__(*exc_details)
+
+
class MessageTemplateClient(MessageTemplateClientOperationsMixin): # pylint: disable=client-accepts-api-version-keyword
"""MessageTemplateClient.
:param endpoint: The communication resource, for example
https://my-resource.communication.azure.com. Required.
:type endpoint: str
- :param credential: Credential needed for the client to connect to Azure. Is either a
+ :param credential: Credential used to authenticate requests to the service. Is either a
TokenCredential type or a AzureKeyCredential 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 "2024-02-01".
+ :keyword api_version: The API version to use for this operation. Default value is "2024-08-30".
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:
- _endpoint = '{endpoint}'
+ def __init__(self, endpoint: str, credential: Union["TokenCredential", AzureKeyCredential], **kwargs: Any) -> None:
+ _endpoint = "{endpoint}"
self._config = MessageTemplateClientConfiguration(endpoint=endpoint, credential=credential, **kwargs)
- _policies = kwargs.pop('policies', None)
+ _policies = kwargs.pop("policies", None)
if _policies is None:
- _policies = [policies.RequestIdPolicy(**kwargs),self._config.headers_policy,self._config.user_agent_policy,
- self._config.proxy_policy,policies.ContentDecodePolicy(**kwargs),self._config.redirect_policy,
- self._config.retry_policy,self._config.authentication_policy,self._config.custom_hook_policy,
- self._config.logging_policy,policies.DistributedTracingPolicy(**kwargs),
- policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None,
- self._config.http_logging_policy]
+ _policies = [
+ policies.RequestIdPolicy(**kwargs),
+ self._config.headers_policy,
+ self._config.user_agent_policy,
+ self._config.proxy_policy,
+ policies.ContentDecodePolicy(**kwargs),
+ self._config.redirect_policy,
+ self._config.retry_policy,
+ self._config.authentication_policy,
+ self._config.custom_hook_policy,
+ self._config.logging_policy,
+ policies.DistributedTracingPolicy(**kwargs),
+ policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None,
+ self._config.http_logging_policy,
+ ]
self._client: PipelineClient = PipelineClient(base_url=_endpoint, policies=_policies, **kwargs)
-
self._serialize = Serializer()
self._deserialize = Deserializer()
self._serialize.client_side_validation = False
-
- def send_request(
- self,
- request: HttpRequest, *, stream: bool = False,
- **kwargs: Any
- ) -> HttpResponse:
+ def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs: Any) -> HttpResponse:
"""Runs the network request through the client's chained policies.
>>> from azure.core.rest import HttpRequest
@@ -166,7 +165,7 @@ def send_request(
request_copy = deepcopy(request)
path_format_arguments = {
- "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, 'str', skip_quote=True),
+ "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
}
request_copy.url = self._client.format_url(request_copy.url, **path_format_arguments)
@@ -175,7 +174,7 @@ def send_request(
def close(self) -> None:
self._client.close()
- def __enter__(self) -> "MessageTemplateClient":
+ def __enter__(self) -> Self:
self._client.__enter__()
return self
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 c2a1df548b8b..068efb0f2106 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/_configuration.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_configuration.py
@@ -18,7 +18,7 @@
from azure.core.credentials import TokenCredential
-class NotificationMessagesClientConfiguration: # pylint: disable=too-many-instance-attributes,name-too-long
+class NotificationMessagesClientConfiguration: # pylint: disable=too-many-instance-attributes,name-too-long
"""Configuration for NotificationMessagesClient.
Note that all parameters used to create this instance are saved as instance
@@ -27,22 +27,17 @@ class NotificationMessagesClientConfiguration: # pylint: disable=too-many-ins
:param endpoint: The communication resource, for example
https://my-resource.communication.azure.com. Required.
:type endpoint: str
- :param credential: Credential needed for the client to connect to Azure. Is either a
+ :param credential: Credential used to authenticate requests to the service. Is either a
TokenCredential type or a AzureKeyCredential 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 "2024-02-01".
+ :keyword api_version: The API version to use for this operation. Default value is "2024-08-30".
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:
- api_version: str = kwargs.pop('api_version', "2024-02-01")
+ def __init__(self, endpoint: str, credential: Union["TokenCredential", AzureKeyCredential], **kwargs: Any) -> None:
+ api_version: str = kwargs.pop("api_version", "2024-08-30")
if endpoint is None:
raise ValueError("Parameter 'endpoint' must not be None.")
@@ -52,34 +47,33 @@ def __init__(
self.endpoint = endpoint
self.credential = credential
self.api_version = api_version
- self.credential_scopes = kwargs.pop('credential_scopes', ['https://communication.azure.com/.default'])
- kwargs.setdefault('sdk_moniker', 'communication-messages/{}'.format(VERSION))
+ self.credential_scopes = kwargs.pop("credential_scopes", ["https://communication.azure.com/.default"])
+ kwargs.setdefault("sdk_moniker", "communication-messages/{}".format(VERSION))
self.polling_interval = kwargs.get("polling_interval", 30)
self._configure(**kwargs)
def _infer_policy(self, **kwargs):
- if hasattr(self.credential, 'get_token'):
+ if hasattr(self.credential, "get_token"):
return policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs)
if isinstance(self.credential, AzureKeyCredential):
return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", **kwargs)
raise TypeError(f"Unsupported credential: {self.credential}")
- def _configure(
- self,
- **kwargs: Any
- ) -> None:
- self.user_agent_policy = kwargs.get('user_agent_policy') or policies.UserAgentPolicy(**kwargs)
- self.headers_policy = kwargs.get('headers_policy') or policies.HeadersPolicy(**kwargs)
- self.proxy_policy = kwargs.get('proxy_policy') or policies.ProxyPolicy(**kwargs)
- self.logging_policy = kwargs.get('logging_policy') or policies.NetworkTraceLoggingPolicy(**kwargs)
- self.http_logging_policy = kwargs.get('http_logging_policy') or policies.HttpLoggingPolicy(**kwargs)
- self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs)
- self.redirect_policy = kwargs.get('redirect_policy') or policies.RedirectPolicy(**kwargs)
- self.retry_policy = kwargs.get('retry_policy') or policies.RetryPolicy(**kwargs)
- self.authentication_policy = kwargs.get('authentication_policy')
+ def _configure(self, **kwargs: Any) -> None:
+ self.user_agent_policy = kwargs.get("user_agent_policy") or policies.UserAgentPolicy(**kwargs)
+ self.headers_policy = kwargs.get("headers_policy") or policies.HeadersPolicy(**kwargs)
+ self.proxy_policy = kwargs.get("proxy_policy") or policies.ProxyPolicy(**kwargs)
+ self.logging_policy = kwargs.get("logging_policy") or policies.NetworkTraceLoggingPolicy(**kwargs)
+ self.http_logging_policy = kwargs.get("http_logging_policy") or policies.HttpLoggingPolicy(**kwargs)
+ self.custom_hook_policy = kwargs.get("custom_hook_policy") or policies.CustomHookPolicy(**kwargs)
+ self.redirect_policy = kwargs.get("redirect_policy") or policies.RedirectPolicy(**kwargs)
+ self.retry_policy = kwargs.get("retry_policy") or policies.RetryPolicy(**kwargs)
+ self.authentication_policy = kwargs.get("authentication_policy")
if self.credential and not self.authentication_policy:
self.authentication_policy = self._infer_policy(**kwargs)
-class MessageTemplateClientConfiguration: # pylint: disable=too-many-instance-attributes,name-too-long
+
+
+class MessageTemplateClientConfiguration: # pylint: disable=too-many-instance-attributes,name-too-long
"""Configuration for MessageTemplateClient.
Note that all parameters used to create this instance are saved as instance
@@ -88,22 +82,17 @@ class MessageTemplateClientConfiguration: # pylint: disable=too-many-instance
:param endpoint: The communication resource, for example
https://my-resource.communication.azure.com. Required.
:type endpoint: str
- :param credential: Credential needed for the client to connect to Azure. Is either a
+ :param credential: Credential used to authenticate requests to the service. Is either a
TokenCredential type or a AzureKeyCredential 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 "2024-02-01".
+ :keyword api_version: The API version to use for this operation. Default value is "2024-08-30".
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:
- api_version: str = kwargs.pop('api_version', "2024-02-01")
+ def __init__(self, endpoint: str, credential: Union["TokenCredential", AzureKeyCredential], **kwargs: Any) -> None:
+ api_version: str = kwargs.pop("api_version", "2024-08-30")
if endpoint is None:
raise ValueError("Parameter 'endpoint' must not be None.")
@@ -113,30 +102,27 @@ def __init__(
self.endpoint = endpoint
self.credential = credential
self.api_version = api_version
- self.credential_scopes = kwargs.pop('credential_scopes', ['https://communication.azure.com/.default'])
- kwargs.setdefault('sdk_moniker', 'communication-messages/{}'.format(VERSION))
+ self.credential_scopes = kwargs.pop("credential_scopes", ["https://communication.azure.com/.default"])
+ kwargs.setdefault("sdk_moniker", "communication-messages/{}".format(VERSION))
self.polling_interval = kwargs.get("polling_interval", 30)
self._configure(**kwargs)
def _infer_policy(self, **kwargs):
- if hasattr(self.credential, 'get_token'):
+ if hasattr(self.credential, "get_token"):
return policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs)
if isinstance(self.credential, AzureKeyCredential):
return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", **kwargs)
raise TypeError(f"Unsupported credential: {self.credential}")
- def _configure(
- self,
- **kwargs: Any
- ) -> None:
- self.user_agent_policy = kwargs.get('user_agent_policy') or policies.UserAgentPolicy(**kwargs)
- self.headers_policy = kwargs.get('headers_policy') or policies.HeadersPolicy(**kwargs)
- self.proxy_policy = kwargs.get('proxy_policy') or policies.ProxyPolicy(**kwargs)
- self.logging_policy = kwargs.get('logging_policy') or policies.NetworkTraceLoggingPolicy(**kwargs)
- self.http_logging_policy = kwargs.get('http_logging_policy') or policies.HttpLoggingPolicy(**kwargs)
- self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs)
- self.redirect_policy = kwargs.get('redirect_policy') or policies.RedirectPolicy(**kwargs)
- self.retry_policy = kwargs.get('retry_policy') or policies.RetryPolicy(**kwargs)
- self.authentication_policy = kwargs.get('authentication_policy')
+ def _configure(self, **kwargs: Any) -> None:
+ self.user_agent_policy = kwargs.get("user_agent_policy") or policies.UserAgentPolicy(**kwargs)
+ self.headers_policy = kwargs.get("headers_policy") or policies.HeadersPolicy(**kwargs)
+ self.proxy_policy = kwargs.get("proxy_policy") or policies.ProxyPolicy(**kwargs)
+ self.logging_policy = kwargs.get("logging_policy") or policies.NetworkTraceLoggingPolicy(**kwargs)
+ self.http_logging_policy = kwargs.get("http_logging_policy") or policies.HttpLoggingPolicy(**kwargs)
+ self.custom_hook_policy = kwargs.get("custom_hook_policy") or policies.CustomHookPolicy(**kwargs)
+ self.redirect_policy = kwargs.get("redirect_policy") or policies.RedirectPolicy(**kwargs)
+ self.retry_policy = kwargs.get("retry_policy") or policies.RetryPolicy(**kwargs)
+ self.authentication_policy = kwargs.get("authentication_policy")
if self.credential and not self.authentication_policy:
self.authentication_policy = self._infer_policy(**kwargs)
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 ebf9c5fcb0dd..12ad7f29c71e 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
@@ -4,8 +4,9 @@
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
-# pylint: disable=protected-access, arguments-differ, signature-differs, broad-except
+# pylint: disable=protected-access, arguments-differ, signature-differs, broad-except, too-many-lines
+import copy
import calendar
import decimal
import functools
@@ -13,12 +14,12 @@
import logging
import base64
import re
-import copy
import typing
import enum
import email.utils
from datetime import datetime, date, time, timedelta, timezone
from json import JSONEncoder
+import xml.etree.ElementTree as ET
from typing_extensions import Self
import isodate
from azure.core.exceptions import DeserializationError
@@ -123,7 +124,7 @@ def _serialize_datetime(o, format: typing.Optional[str] = None):
def _is_readonly(p):
try:
- return p._visibility == ["read"] # pylint: disable=protected-access
+ return p._visibility == ["read"]
except AttributeError:
return False
@@ -286,6 +287,12 @@ def _deserialize_decimal(attr):
return decimal.Decimal(str(attr))
+def _deserialize_int_as_str(attr):
+ if isinstance(attr, int):
+ return attr
+ return int(attr)
+
+
_DESERIALIZE_MAPPING = {
datetime: _deserialize_datetime,
date: _deserialize_date,
@@ -307,9 +314,11 @@ def _deserialize_decimal(attr):
def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] = None):
+ if annotation is int and rf and rf._format == "str":
+ return _deserialize_int_as_str
if rf and rf._format:
return _DESERIALIZE_MAPPING_WITHFORMAT.get(rf._format)
- return _DESERIALIZE_MAPPING.get(annotation)
+ return _DESERIALIZE_MAPPING.get(annotation) # pyright: ignore
def _get_type_alias_type(module_name: str, alias_name: str):
@@ -324,17 +333,9 @@ def _get_type_alias_type(module_name: str, alias_name: str):
def _get_model(module_name: str, model_name: str):
- models = {
- k: v
- for k, v in sys.modules[module_name].__dict__.items()
- if isinstance(v, type)
- }
+ models = {k: v for k, v in sys.modules[module_name].__dict__.items() if isinstance(v, type)}
module_end = module_name.rsplit(".", 1)[0]
- models.update({
- k: v
- for k, v in sys.modules[module_end].__dict__.items()
- if isinstance(v, type)
- })
+ models.update({k: v for k, v in sys.modules[module_end].__dict__.items() if isinstance(v, type)})
if isinstance(model_name, str):
model_name = model_name.split(".")[-1]
if model_name not in models:
@@ -347,7 +348,7 @@ def _get_model(module_name: str, model_name: str):
class _MyMutableMapping(MutableMapping[str, typing.Any]): # pylint: disable=unsubscriptable-object
def __init__(self, data: typing.Dict[str, typing.Any]) -> None:
- self._data = copy.deepcopy(data)
+ self._data = data
def __contains__(self, key: typing.Any) -> bool:
return key in self._data
@@ -386,16 +387,13 @@ def get(self, key: str, default: typing.Any = None) -> typing.Any:
return default
@typing.overload
- def pop(self, key: str) -> typing.Any:
- ...
+ def pop(self, key: str) -> typing.Any: ...
@typing.overload
- def pop(self, key: str, default: _T) -> _T:
- ...
+ def pop(self, key: str, default: _T) -> _T: ...
@typing.overload
- def pop(self, key: str, default: typing.Any) -> typing.Any:
- ...
+ def pop(self, key: str, default: typing.Any) -> typing.Any: ...
def pop(self, key: str, default: typing.Any = _UNSET) -> typing.Any:
if default is _UNSET:
@@ -412,12 +410,10 @@ def update(self, *args: typing.Any, **kwargs: typing.Any) -> None:
self._data.update(*args, **kwargs)
@typing.overload
- def setdefault(self, key: str, default: None = None) -> None:
- ...
+ def setdefault(self, key: str, default: None = None) -> None: ...
@typing.overload
- def setdefault(self, key: str, default: typing.Any) -> typing.Any:
- ...
+ def setdefault(self, key: str, default: typing.Any) -> typing.Any: ...
def setdefault(self, key: str, default: typing.Any = _UNSET) -> typing.Any:
if default is _UNSET:
@@ -454,6 +450,10 @@ def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-m
return float(o)
if isinstance(o, enum.Enum):
return o.value
+ if isinstance(o, int):
+ if format == "str":
+ return str(o)
+ return o
try:
# First try datetime.datetime
return _serialize_datetime(o, format)
@@ -484,11 +484,16 @@ def _create_value(rf: typing.Optional["_RestField"], value: typing.Any) -> typin
return value
if rf._is_model:
return _deserialize(rf._type, value)
+ if isinstance(value, ET.Element):
+ value = _deserialize(rf._type, value)
return _serialize(value, rf._format)
class Model(_MyMutableMapping):
_is_model = True
+ # label whether current class's _attr_to_rest_field has been calculated
+ # could not see _attr_to_rest_field directly because subclass inherits it from parent class
+ _calculated: typing.Set[str] = set()
def __init__(self, *args: typing.Any, **kwargs: typing.Any) -> None:
class_name = self.__class__.__name__
@@ -499,10 +504,58 @@ def __init__(self, *args: typing.Any, **kwargs: typing.Any) -> None:
for rest_field in self._attr_to_rest_field.values()
if rest_field._default is not _UNSET
}
- if args:
- dict_to_pass.update(
- {k: _create_value(_get_rest_field(self._attr_to_rest_field, k), v) for k, v in args[0].items()}
- )
+ if args: # pylint: disable=too-many-nested-blocks
+ if isinstance(args[0], ET.Element):
+ existed_attr_keys = []
+ model_meta = getattr(self, "_xml", {})
+
+ for rf in self._attr_to_rest_field.values():
+ prop_meta = getattr(rf, "_xml", {})
+ xml_name = prop_meta.get("name", rf._rest_name)
+ xml_ns = prop_meta.get("ns", model_meta.get("ns", None))
+ if xml_ns:
+ xml_name = "{" + xml_ns + "}" + xml_name
+
+ # attribute
+ if prop_meta.get("attribute", False) and args[0].get(xml_name) is not None:
+ existed_attr_keys.append(xml_name)
+ dict_to_pass[rf._rest_name] = _deserialize(rf._type, args[0].get(xml_name))
+ continue
+
+ # unwrapped element is array
+ if prop_meta.get("unwrapped", False):
+ # unwrapped array could either use prop items meta/prop meta
+ if prop_meta.get("itemsName"):
+ xml_name = prop_meta.get("itemsName")
+ xml_ns = prop_meta.get("itemNs")
+ if xml_ns:
+ xml_name = "{" + xml_ns + "}" + xml_name
+ items = args[0].findall(xml_name) # pyright: ignore
+ if len(items) > 0:
+ existed_attr_keys.append(xml_name)
+ dict_to_pass[rf._rest_name] = _deserialize(rf._type, items)
+ continue
+
+ # text element is primitive type
+ if prop_meta.get("text", False):
+ if args[0].text is not None:
+ dict_to_pass[rf._rest_name] = _deserialize(rf._type, args[0].text)
+ continue
+
+ # wrapped element could be normal property or array, it should only have one element
+ item = args[0].find(xml_name)
+ if item is not None:
+ existed_attr_keys.append(xml_name)
+ dict_to_pass[rf._rest_name] = _deserialize(rf._type, item)
+
+ # rest thing is additional properties
+ for e in args[0]:
+ if e.tag not in existed_attr_keys:
+ dict_to_pass[e.tag] = _convert_element(e)
+ else:
+ dict_to_pass.update(
+ {k: _create_value(_get_rest_field(self._attr_to_rest_field, k), v) for k, v in args[0].items()}
+ )
else:
non_attr_kwargs = [k for k in kwargs if k not in self._attr_to_rest_field]
if non_attr_kwargs:
@@ -521,24 +574,27 @@ def copy(self) -> "Model":
return Model(self.__dict__)
def __new__(cls, *args: typing.Any, **kwargs: typing.Any) -> Self: # pylint: disable=unused-argument
- # we know the last three classes in mro are going to be 'Model', 'dict', and 'object'
- mros = cls.__mro__[:-3][::-1] # ignore model, dict, and object parents, and reverse the mro order
- attr_to_rest_field: typing.Dict[str, _RestField] = { # map attribute name to rest_field property
- k: v for mro_class in mros for k, v in mro_class.__dict__.items() if k[0] != "_" and hasattr(v, "_type")
- }
- annotations = {
- k: v
- for mro_class in mros
- if hasattr(mro_class, "__annotations__") # pylint: disable=no-member
- for k, v in mro_class.__annotations__.items() # pylint: disable=no-member
- }
- for attr, rf in attr_to_rest_field.items():
- rf._module = cls.__module__
- if not rf._type:
- rf._type = rf._get_deserialize_callable_from_annotation(annotations.get(attr, None))
- if not rf._rest_name_input:
- rf._rest_name_input = attr
- cls._attr_to_rest_field: typing.Dict[str, _RestField] = dict(attr_to_rest_field.items())
+ if f"{cls.__module__}.{cls.__qualname__}" not in cls._calculated:
+ # we know the last nine classes in mro are going to be 'Model', '_MyMutableMapping', 'MutableMapping',
+ # 'Mapping', 'Collection', 'Sized', 'Iterable', 'Container' and 'object'
+ mros = cls.__mro__[:-9][::-1] # ignore parents, and reverse the mro order
+ attr_to_rest_field: typing.Dict[str, _RestField] = { # map attribute name to rest_field property
+ k: v for mro_class in mros for k, v in mro_class.__dict__.items() if k[0] != "_" and hasattr(v, "_type")
+ }
+ annotations = {
+ k: v
+ for mro_class in mros
+ if hasattr(mro_class, "__annotations__") # pylint: disable=no-member
+ for k, v in mro_class.__annotations__.items() # pylint: disable=no-member
+ }
+ for attr, rf in attr_to_rest_field.items():
+ rf._module = cls.__module__
+ if not rf._type:
+ rf._type = rf._get_deserialize_callable_from_annotation(annotations.get(attr, None))
+ if not rf._rest_name_input:
+ rf._rest_name_input = attr
+ cls._attr_to_rest_field: typing.Dict[str, _RestField] = dict(attr_to_rest_field.items())
+ cls._calculated.add(f"{cls.__module__}.{cls.__qualname__}")
return super().__new__(cls) # pylint: disable=no-value-for-parameter
@@ -548,10 +604,10 @@ def __init_subclass__(cls, discriminator: typing.Optional[str] = None) -> None:
base.__mapping__[discriminator or cls.__name__] = cls # type: ignore # pylint: disable=no-member
@classmethod
- def _get_discriminator(cls, exist_discriminators) -> typing.Optional[str]:
+ def _get_discriminator(cls, exist_discriminators) -> typing.Optional["_RestField"]:
for v in cls.__dict__.values():
- if isinstance(v, _RestField) and v._is_discriminator and v._rest_name not in exist_discriminators: # pylint: disable=protected-access
- return v._rest_name # pylint: disable=protected-access
+ if isinstance(v, _RestField) and v._is_discriminator and v._rest_name not in exist_discriminators:
+ return v
return None
@classmethod
@@ -559,11 +615,25 @@ def _deserialize(cls, data, exist_discriminators):
if not hasattr(cls, "__mapping__"): # pylint: disable=no-member
return cls(data)
discriminator = cls._get_discriminator(exist_discriminators)
- exist_discriminators.append(discriminator)
- mapped_cls = cls.__mapping__.get(data.get(discriminator), cls) # pyright: ignore # pylint: disable=no-member
- if mapped_cls == cls:
+ if discriminator is None:
return cls(data)
- return mapped_cls._deserialize(data, exist_discriminators) # pylint: disable=protected-access
+ exist_discriminators.append(discriminator._rest_name)
+ if isinstance(data, ET.Element):
+ model_meta = getattr(cls, "_xml", {})
+ prop_meta = getattr(discriminator, "_xml", {})
+ xml_name = prop_meta.get("name", discriminator._rest_name)
+ xml_ns = prop_meta.get("ns", model_meta.get("ns", None))
+ if xml_ns:
+ xml_name = "{" + xml_ns + "}" + xml_name
+
+ if data.get(xml_name) is not None:
+ discriminator_value = data.get(xml_name)
+ else:
+ discriminator_value = data.find(xml_name).text # pyright: ignore
+ else:
+ discriminator_value = data.get(discriminator._rest_name)
+ mapped_cls = cls.__mapping__.get(discriminator_value, cls) # pyright: ignore # pylint: disable=no-member
+ return mapped_cls._deserialize(data, exist_discriminators)
def as_dict(self, *, exclude_readonly: bool = False) -> typing.Dict[str, typing.Any]:
"""Return a dict that can be JSONify using json.dump.
@@ -574,6 +644,7 @@ def as_dict(self, *, exclude_readonly: bool = False) -> typing.Dict[str, typing.
"""
result = {}
+ readonly_props = []
if exclude_readonly:
readonly_props = [p._rest_name for p in self._attr_to_rest_field.values() if _is_readonly(p)]
for k, v in self.items():
@@ -581,8 +652,9 @@ def as_dict(self, *, exclude_readonly: bool = False) -> typing.Dict[str, typing.
continue
is_multipart_file_input = False
try:
- is_multipart_file_input = next(rf for rf in self._attr_to_rest_field.values()
- if rf._rest_name == k)._is_multipart_file_input
+ is_multipart_file_input = next(
+ rf for rf in self._attr_to_rest_field.values() if rf._rest_name == k
+ )._is_multipart_file_input
except StopIteration:
pass
result[k] = v if is_multipart_file_input else Model._as_dict_value(v, exclude_readonly=exclude_readonly)
@@ -593,24 +665,80 @@ def _as_dict_value(v: typing.Any, exclude_readonly: bool = False) -> typing.Any:
if v is None or isinstance(v, _Null):
return None
if isinstance(v, (list, tuple, set)):
- return type(v)(
- Model._as_dict_value(x, exclude_readonly=exclude_readonly)
- for x in v
- )
+ return type(v)(Model._as_dict_value(x, exclude_readonly=exclude_readonly) for x in v)
if isinstance(v, dict):
- return {
- dk: Model._as_dict_value(dv, exclude_readonly=exclude_readonly)
- for dk, dv in v.items()
- }
+ return {dk: Model._as_dict_value(dv, exclude_readonly=exclude_readonly) for dk, dv in v.items()}
return v.as_dict(exclude_readonly=exclude_readonly) if hasattr(v, "as_dict") else v
+def _deserialize_model(model_deserializer: typing.Optional[typing.Callable], obj):
+ if _is_model(obj):
+ return obj
+ return _deserialize(model_deserializer, obj)
+
+
+def _deserialize_with_optional(if_obj_deserializer: typing.Optional[typing.Callable], obj):
+ if obj is None:
+ return obj
+ return _deserialize_with_callable(if_obj_deserializer, obj)
+
+
+def _deserialize_with_union(deserializers, obj):
+ for deserializer in deserializers:
+ try:
+ return _deserialize(deserializer, obj)
+ except DeserializationError:
+ pass
+ raise DeserializationError()
+
+
+def _deserialize_dict(
+ value_deserializer: typing.Optional[typing.Callable],
+ module: typing.Optional[str],
+ obj: typing.Dict[typing.Any, typing.Any],
+):
+ if obj is None:
+ return obj
+ if isinstance(obj, ET.Element):
+ obj = {child.tag: child for child in obj}
+ return {k: _deserialize(value_deserializer, v, module) for k, v in obj.items()}
+
+
+def _deserialize_multiple_sequence(
+ entry_deserializers: typing.List[typing.Optional[typing.Callable]],
+ module: typing.Optional[str],
+ obj,
+):
+ if obj is None:
+ return obj
+ return type(obj)(_deserialize(deserializer, entry, module) for entry, deserializer in zip(obj, entry_deserializers))
+
+
+def _deserialize_sequence(
+ deserializer: typing.Optional[typing.Callable],
+ module: typing.Optional[str],
+ obj,
+):
+ if obj is None:
+ return obj
+ if isinstance(obj, ET.Element):
+ obj = list(obj)
+ return type(obj)(_deserialize(deserializer, entry, module) for entry in obj)
+
+
+def _sorted_annotations(types: typing.List[typing.Any]) -> typing.List[typing.Any]:
+ return sorted(
+ types,
+ key=lambda x: hasattr(x, "__name__") and x.__name__.lower() in ("str", "float", "int", "bool"),
+ )
+
+
def _get_deserialize_callable_from_annotation( # pylint: disable=R0911, R0915, R0912
annotation: typing.Any,
module: typing.Optional[str],
rf: typing.Optional["_RestField"] = None,
) -> typing.Optional[typing.Callable[[typing.Any], typing.Any]]:
- if not annotation or annotation in [int, float]:
+ if not annotation:
return None
# is it a type alias?
@@ -632,11 +760,6 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=R0911, R0915,
if rf:
rf._is_model = True
- def _deserialize_model(model_deserializer: typing.Optional[typing.Callable], obj):
- if _is_model(obj):
- return obj
- return _deserialize(model_deserializer, obj)
-
return functools.partial(_deserialize_model, annotation) # pyright: ignore
except Exception:
pass
@@ -651,36 +774,27 @@ def _deserialize_model(model_deserializer: typing.Optional[typing.Callable], obj
# is it optional?
try:
if any(a for a in annotation.__args__ if a == type(None)): # pyright: ignore
- if_obj_deserializer = _get_deserialize_callable_from_annotation(
- next(a for a in annotation.__args__ if a != type(None)), module, rf # pyright: ignore
- )
-
- def _deserialize_with_optional(if_obj_deserializer: typing.Optional[typing.Callable], obj):
- if obj is None:
- return obj
- return _deserialize_with_callable(if_obj_deserializer, obj)
-
- return functools.partial(_deserialize_with_optional, if_obj_deserializer)
+ if len(annotation.__args__) <= 2: # pyright: ignore
+ if_obj_deserializer = _get_deserialize_callable_from_annotation(
+ next(a for a in annotation.__args__ if a != type(None)), module, rf # pyright: ignore
+ )
+
+ return functools.partial(_deserialize_with_optional, if_obj_deserializer)
+ # the type is Optional[Union[...]], we need to remove the None type from the Union
+ annotation_copy = copy.copy(annotation)
+ annotation_copy.__args__ = [a for a in annotation_copy.__args__ if a != type(None)] # pyright: ignore
+ return _get_deserialize_callable_from_annotation(annotation_copy, module, rf)
except AttributeError:
pass
+ # is it union?
if getattr(annotation, "__origin__", None) is typing.Union:
# initial ordering is we make `string` the last deserialization option, because it is often them most generic
deserializers = [
_get_deserialize_callable_from_annotation(arg, module, rf)
- for arg in sorted(
- annotation.__args__, key=lambda x: hasattr(x, "__name__") and x.__name__ == "str" # pyright: ignore
- )
+ for arg in _sorted_annotations(annotation.__args__) # pyright: ignore
]
- def _deserialize_with_union(deserializers, obj):
- for deserializer in deserializers:
- try:
- return _deserialize(deserializer, obj)
- except DeserializationError:
- pass
- raise DeserializationError()
-
return functools.partial(_deserialize_with_union, deserializers)
try:
@@ -689,56 +803,26 @@ def _deserialize_with_union(deserializers, obj):
annotation.__args__[1], module, rf # pyright: ignore
)
- def _deserialize_dict(
- value_deserializer: typing.Optional[typing.Callable],
- obj: typing.Dict[typing.Any, typing.Any],
- ):
- if obj is None:
- return obj
- return {
- k: _deserialize(value_deserializer, v, module)
- for k, v in obj.items()
- }
-
return functools.partial(
_deserialize_dict,
value_deserializer,
+ module,
)
except (AttributeError, IndexError):
pass
try:
if annotation._name in ["List", "Set", "Tuple", "Sequence"]: # pyright: ignore
if len(annotation.__args__) > 1: # pyright: ignore
-
- def _deserialize_multiple_sequence(
- entry_deserializers: typing.List[typing.Optional[typing.Callable]],
- obj,
- ):
- if obj is None:
- return obj
- return type(obj)(
- _deserialize(deserializer, entry, module)
- for entry, deserializer in zip(obj, entry_deserializers)
- )
-
entry_deserializers = [
_get_deserialize_callable_from_annotation(dt, module, rf)
- for dt in annotation.__args__ # pyright: ignore
+ for dt in annotation.__args__ # pyright: ignore
]
- return functools.partial(_deserialize_multiple_sequence, entry_deserializers)
+ return functools.partial(_deserialize_multiple_sequence, entry_deserializers, module)
deserializer = _get_deserialize_callable_from_annotation(
annotation.__args__[0], module, rf # pyright: ignore
)
- def _deserialize_sequence(
- deserializer: typing.Optional[typing.Callable],
- obj,
- ):
- if obj is None:
- return obj
- return type(obj)(_deserialize(deserializer, entry, module) for entry in obj)
-
- return functools.partial(_deserialize_sequence, deserializer)
+ return functools.partial(_deserialize_sequence, deserializer, module)
except (TypeError, IndexError, AttributeError, SyntaxError):
pass
@@ -763,12 +847,23 @@ def _deserialize_default(
def _deserialize_with_callable(
deserializer: typing.Optional[typing.Callable[[typing.Any], typing.Any]],
value: typing.Any,
-):
+): # pylint: disable=too-many-return-statements
try:
if value is None or isinstance(value, _Null):
return None
+ if isinstance(value, ET.Element):
+ if deserializer is str:
+ return value.text or ""
+ if deserializer is int:
+ return int(value.text) if value.text else None
+ if deserializer is float:
+ return float(value.text) if value.text else None
+ if deserializer is bool:
+ return value.text == "true" if value.text else None
if deserializer is None:
return value
+ if deserializer in [int, float, bool]:
+ return deserializer(value)
if isinstance(deserializer, CaseInsensitiveEnumMeta):
try:
return deserializer(value)
@@ -809,6 +904,7 @@ def __init__(
default: typing.Any = _UNSET,
format: typing.Optional[str] = None,
is_multipart_file_input: bool = False,
+ xml: typing.Optional[typing.Dict[str, typing.Any]] = None,
):
self._type = type
self._rest_name_input = name
@@ -819,6 +915,7 @@ def __init__(
self._default = default
self._format = format
self._is_multipart_file_input = is_multipart_file_input
+ self._xml = xml if xml is not None else {}
@property
def _class_type(self) -> typing.Any:
@@ -869,6 +966,7 @@ def rest_field(
default: typing.Any = _UNSET,
format: typing.Optional[str] = None,
is_multipart_file_input: bool = False,
+ xml: typing.Optional[typing.Dict[str, typing.Any]] = None,
) -> typing.Any:
return _RestField(
name=name,
@@ -876,11 +974,185 @@ def rest_field(
visibility=visibility,
default=default,
format=format,
- is_multipart_file_input=is_multipart_file_input)
+ is_multipart_file_input=is_multipart_file_input,
+ xml=xml,
+ )
+
def rest_discriminator(
*,
name: typing.Optional[str] = None,
type: typing.Optional[typing.Callable] = None, # pylint: disable=redefined-builtin
+ visibility: typing.Optional[typing.List[str]] = None,
+ xml: typing.Optional[typing.Dict[str, typing.Any]] = None,
) -> typing.Any:
- return _RestField(name=name, type=type, is_discriminator=True)
+ return _RestField(name=name, type=type, is_discriminator=True, visibility=visibility, xml=xml)
+
+
+def serialize_xml(model: Model, exclude_readonly: bool = False) -> str:
+ """Serialize a model to XML.
+
+ :param Model model: The model to serialize.
+ :param bool exclude_readonly: Whether to exclude readonly properties.
+ :returns: The XML representation of the model.
+ :rtype: str
+ """
+ return ET.tostring(_get_element(model, exclude_readonly), encoding="unicode") # type: ignore
+
+
+def _get_element(
+ o: typing.Any,
+ exclude_readonly: bool = False,
+ parent_meta: typing.Optional[typing.Dict[str, typing.Any]] = None,
+ wrapped_element: typing.Optional[ET.Element] = None,
+) -> typing.Union[ET.Element, typing.List[ET.Element]]:
+ if _is_model(o):
+ model_meta = getattr(o, "_xml", {})
+
+ # if prop is a model, then use the prop element directly, else generate a wrapper of model
+ if wrapped_element is None:
+ wrapped_element = _create_xml_element(
+ model_meta.get("name", o.__class__.__name__),
+ model_meta.get("prefix"),
+ model_meta.get("ns"),
+ )
+
+ readonly_props = []
+ if exclude_readonly:
+ readonly_props = [p._rest_name for p in o._attr_to_rest_field.values() if _is_readonly(p)]
+
+ for k, v in o.items():
+ # do not serialize readonly properties
+ if exclude_readonly and k in readonly_props:
+ continue
+
+ prop_rest_field = _get_rest_field(o._attr_to_rest_field, k)
+ if prop_rest_field:
+ prop_meta = getattr(prop_rest_field, "_xml").copy()
+ # use the wire name as xml name if no specific name is set
+ if prop_meta.get("name") is None:
+ prop_meta["name"] = k
+ else:
+ # additional properties will not have rest field, use the wire name as xml name
+ prop_meta = {"name": k}
+
+ # if no ns for prop, use model's
+ if prop_meta.get("ns") is None and model_meta.get("ns"):
+ prop_meta["ns"] = model_meta.get("ns")
+ prop_meta["prefix"] = model_meta.get("prefix")
+
+ if prop_meta.get("unwrapped", False):
+ # unwrapped could only set on array
+ wrapped_element.extend(_get_element(v, exclude_readonly, prop_meta))
+ elif prop_meta.get("text", False):
+ # text could only set on primitive type
+ wrapped_element.text = _get_primitive_type_value(v)
+ elif prop_meta.get("attribute", False):
+ xml_name = prop_meta.get("name", k)
+ if prop_meta.get("ns"):
+ ET.register_namespace(prop_meta.get("prefix"), prop_meta.get("ns")) # pyright: ignore
+ xml_name = "{" + prop_meta.get("ns") + "}" + xml_name # pyright: ignore
+ # attribute should be primitive type
+ wrapped_element.set(xml_name, _get_primitive_type_value(v))
+ else:
+ # other wrapped prop element
+ wrapped_element.append(_get_wrapped_element(v, exclude_readonly, prop_meta))
+ return wrapped_element
+ if isinstance(o, list):
+ return [_get_element(x, exclude_readonly, parent_meta) for x in o] # type: ignore
+ if isinstance(o, dict):
+ result = []
+ for k, v in o.items():
+ result.append(
+ _get_wrapped_element(
+ v,
+ exclude_readonly,
+ {
+ "name": k,
+ "ns": parent_meta.get("ns") if parent_meta else None,
+ "prefix": parent_meta.get("prefix") if parent_meta else None,
+ },
+ )
+ )
+ return result
+
+ # primitive case need to create element based on parent_meta
+ if parent_meta:
+ return _get_wrapped_element(
+ o,
+ exclude_readonly,
+ {
+ "name": parent_meta.get("itemsName", parent_meta.get("name")),
+ "prefix": parent_meta.get("itemsPrefix", parent_meta.get("prefix")),
+ "ns": parent_meta.get("itemsNs", parent_meta.get("ns")),
+ },
+ )
+
+ raise ValueError("Could not serialize value into xml: " + o)
+
+
+def _get_wrapped_element(
+ v: typing.Any,
+ exclude_readonly: bool,
+ meta: typing.Optional[typing.Dict[str, typing.Any]],
+) -> ET.Element:
+ wrapped_element = _create_xml_element(
+ meta.get("name") if meta else None, meta.get("prefix") if meta else None, meta.get("ns") if meta else None
+ )
+ if isinstance(v, (dict, list)):
+ wrapped_element.extend(_get_element(v, exclude_readonly, meta))
+ elif _is_model(v):
+ _get_element(v, exclude_readonly, meta, wrapped_element)
+ else:
+ wrapped_element.text = _get_primitive_type_value(v)
+ return wrapped_element
+
+
+def _get_primitive_type_value(v) -> str:
+ if v is True:
+ return "true"
+ if v is False:
+ return "false"
+ if isinstance(v, _Null):
+ return ""
+ return str(v)
+
+
+def _create_xml_element(tag, prefix=None, ns=None):
+ if prefix and ns:
+ ET.register_namespace(prefix, ns)
+ if ns:
+ return ET.Element("{" + ns + "}" + tag)
+ return ET.Element(tag)
+
+
+def _deserialize_xml(
+ deserializer: typing.Any,
+ value: str,
+) -> typing.Any:
+ element = ET.fromstring(value) # nosec
+ return _deserialize(deserializer, element)
+
+
+def _convert_element(e: ET.Element):
+ # dict case
+ if len(e.attrib) > 0 or len({child.tag for child in e}) > 1:
+ dict_result: typing.Dict[str, typing.Any] = {}
+ for child in e:
+ if dict_result.get(child.tag) is not None:
+ if isinstance(dict_result[child.tag], list):
+ dict_result[child.tag].append(_convert_element(child))
+ else:
+ dict_result[child.tag] = [dict_result[child.tag], _convert_element(child)]
+ else:
+ dict_result[child.tag] = _convert_element(child)
+ dict_result.update(e.attrib)
+ return dict_result
+ # array case
+ if len(e) > 0:
+ array_result: typing.List[typing.Any] = []
+ for child in e:
+ array_result.append(_convert_element(child))
+ return array_result
+ # primitive case
+ return e.text
diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/__init__.py
index b610e644f4c2..5a3a47e6ff3a 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/__init__.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/__init__.py
@@ -12,9 +12,10 @@
from ._patch import __all__ as _patch_all
from ._patch import * # pylint: disable=unused-wildcard-import
from ._patch import patch_sdk as _patch_sdk
+
__all__ = [
- 'NotificationMessagesClientOperationsMixin',
- 'MessageTemplateClientOperationsMixin',
+ "NotificationMessagesClientOperationsMixin",
+ "MessageTemplateClientOperationsMixin",
]
__all__.extend([p for p in _patch_all if p not in __all__])
_patch_sdk()
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 e6cf4c1670a6..981550e5cdd0 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
@@ -10,16 +10,20 @@
from io import IOBase
import json
import sys
-from typing import Any, Callable, Dict, IO, Iterable, Iterator, List, Optional, TypeVar, Union, overload
+from typing import Any, Callable, Dict, IO, Iterable, Iterator, List, Optional, Type, TypeVar, Union, overload
import urllib.parse
import uuid
-from azure.core.exceptions import (ClientAuthenticationError,
- HttpResponseError,
- ResourceExistsError,
- ResourceNotFoundError,
- ResourceNotModifiedError,
- map_error)
+from azure.core.exceptions import (
+ ClientAuthenticationError,
+ HttpResponseError,
+ ResourceExistsError,
+ ResourceNotFoundError,
+ ResourceNotModifiedError,
+ StreamClosedError,
+ StreamConsumedError,
+ map_error,
+)
from azure.core.paging import ItemPaged
from azure.core.pipeline import PipelineResponse
from azure.core.rest import HttpRequest, HttpResponse
@@ -35,134 +39,105 @@
from collections.abc import MutableMapping
else:
from typing import MutableMapping # type: ignore # pylint: disable=ungrouped-imports
-JSON = MutableMapping[str, Any] # pylint: disable=unsubscriptable-object
-T = TypeVar('T')
+JSON = MutableMapping[str, Any] # pylint: disable=unsubscriptable-object
+T = TypeVar("T")
ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]
_SERIALIZER = Serializer()
_SERIALIZER.client_side_validation = False
-def build_notification_messages_send_request(
- **kwargs: Any
-) -> HttpRequest:
+def build_notification_messages_send_request(**kwargs: Any) -> HttpRequest:
_headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
_params = case_insensitive_dict(kwargs.pop("params", {}) or {})
- content_type: Optional[str] = kwargs.pop('content_type', _headers.pop('Content-Type', None))
- api_version: str = kwargs.pop('api_version', _params.pop('api-version', "2024-02-01"))
- accept = _headers.pop('Accept', "application/json")
+ content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
+ api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-08-30"))
+ accept = _headers.pop("Accept", "application/json")
# Construct URL
_url = "/messages/notifications:send"
# Construct parameters
- _params['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')
+ _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")
# Construct headers
if "Repeatability-Request-ID" not in _headers:
_headers["Repeatability-Request-ID"] = str(uuid.uuid4())
if "Repeatability-First-Sent" not in _headers:
_headers["Repeatability-First-Sent"] = _SERIALIZER.serialize_data(
- datetime.datetime.now(datetime.timezone.utc), "rfc-1123")
- _headers['Accept'] = _SERIALIZER.header("accept", accept, 'str')
+ datetime.datetime.now(datetime.timezone.utc), "rfc-1123"
+ )
if content_type is not None:
- _headers['Content-Type'] = _SERIALIZER.header("content_type", content_type, 'str')
+ _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str")
+ _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")
- return HttpRequest(
- method="POST",
- url=_url,
- params=_params,
- headers=_headers,
- **kwargs
- )
+ return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs)
def build_notification_messages_download_media_request( # pylint: disable=name-too-long
- id: str,
- **kwargs: Any
+ id: str, **kwargs: Any
) -> HttpRequest:
_headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
_params = case_insensitive_dict(kwargs.pop("params", {}) or {})
- api_version: str = kwargs.pop('api_version', _params.pop('api-version', "2024-02-01"))
- accept = _headers.pop('Accept', "application/octet-stream")
+ api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-08-30"))
+ accept = _headers.pop("Accept", "application/octet-stream")
# Construct URL
_url = "/messages/streams/{id}"
path_format_arguments = {
- "id": _SERIALIZER.url("id", id, 'str'),
+ "id": _SERIALIZER.url("id", id, "str"),
}
_url: str = _url.format(**path_format_arguments) # type: ignore
# Construct parameters
- _params['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')
+ _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")
# Construct headers
- _headers['Accept'] = _SERIALIZER.header("accept", accept, 'str')
+ _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")
- return HttpRequest(
- method="GET",
- url=_url,
- params=_params,
- headers=_headers,
- **kwargs
- )
+ return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs)
def build_message_template_list_templates_request( # pylint: disable=name-too-long
- channel_id: str,
- *,
- maxpagesize: Optional[int] = None,
- **kwargs: Any
+ channel_id: str, *, maxpagesize: Optional[int] = None, **kwargs: Any
) -> HttpRequest:
_headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
_params = case_insensitive_dict(kwargs.pop("params", {}) or {})
- api_version: str = kwargs.pop('api_version', _params.pop('api-version', "2024-02-01"))
- accept = _headers.pop('Accept', "application/json")
+ api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-08-30"))
+ accept = _headers.pop("Accept", "application/json")
# Construct URL
_url = "/messages/channels/{channelId}/templates"
path_format_arguments = {
- "channelId": _SERIALIZER.url("channel_id", channel_id, 'str'),
+ "channelId": _SERIALIZER.url("channel_id", channel_id, "str"),
}
_url: str = _url.format(**path_format_arguments) # type: ignore
# Construct parameters
- _params['api-version'] = _SERIALIZER.query("api_version", api_version, 'str')
+ _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")
if maxpagesize is not None:
- _params['maxpagesize'] = _SERIALIZER.query("maxpagesize", maxpagesize, 'int')
+ _params["maxpagesize"] = _SERIALIZER.query("maxpagesize", maxpagesize, "int")
# Construct headers
- _headers['Accept'] = _SERIALIZER.header("accept", accept, 'str')
+ _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")
- return HttpRequest(
- method="GET",
- url=_url,
- params=_params,
- headers=_headers,
- **kwargs
- )
+ return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs)
-class NotificationMessagesClientOperationsMixin( # pylint: disable=name-too-long
- NotificationMessagesClientMixinABC
-):
+
+class NotificationMessagesClientOperationsMixin(NotificationMessagesClientMixinABC): # pylint: disable=name-too-long
@overload
def send(
- self,
- body: _models.NotificationContent,
- *,
- content_type: str = "application/json",
- **kwargs: Any
+ self, body: _models.NotificationContent, *, content_type: str = "application/json", **kwargs: Any
) -> _models.SendMessageResult:
- # pylint: disable=line-too-long
"""Sends a notification message from Business to User.
- :param body: Required.
+ :param body: Details of the message to send. Required.
:type body: ~azure.communication.messages.models.NotificationContent
:keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
Default value is "application/json".
@@ -170,117 +145,13 @@ def send(
:return: SendMessageResult. The SendMessageResult is compatible with MutableMapping
:rtype: ~azure.communication.messages.models.SendMessageResult
:raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # The input is polymorphic. The following are possible polymorphic inputs based off
- discriminator "kind":
-
- # JSON input template for discriminator value "image":
- notification_content = {
- "channelRegistrationId": "str", # The Channel Registration ID for the
- Business Identifier. Required.
- "kind": "image",
- "mediaUri": "str", # A media url for the file. Required if the type is one
- of the supported media types, e.g. image. Required.
- "to": [
- "str" # The native external platform user identifiers of the
- recipient. Required.
- ],
- "content": "str" # Optional. Optional text content.
- }
-
- # JSON input template for discriminator value "template":
- notification_content = {
- "channelRegistrationId": "str", # The Channel Registration ID for the
- Business Identifier. Required.
- "kind": "template",
- "template": {
- "language": "str", # 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.
- "name": "str", # Name of the template. Required.
- "bindings": message_template_bindings,
- "values": [
- message_template_value
- ]
- },
- "to": [
- "str" # The native external platform user identifiers of the
- recipient. Required.
- ]
- }
-
- # JSON input template for discriminator value "whatsApp":
- message_template_bindings = {
- "kind": "whatsApp",
- "body": [
- {
- "refValue": "str" # The name of the referenced item in the
- template values. Required.
- }
- ],
- "buttons": [
- {
- "refValue": "str", # The name of the referenced item in the
- template values. Required.
- "subType": "str" # The WhatsApp button sub type. Required.
- Known values are: "quickReply" and "url".
- }
- ],
- "footer": [
- {
- "refValue": "str" # The name of the referenced item in the
- template values. Required.
- }
- ],
- "header": [
- {
- "refValue": "str" # The name of the referenced item in the
- template values. Required.
- }
- ]
- }
-
- # JSON input template for discriminator value "text":
- notification_content = {
- "channelRegistrationId": "str", # The Channel Registration ID for the
- Business Identifier. Required.
- "content": "str", # Message content. Required.
- "kind": "text",
- "to": [
- "str" # The native external platform user identifiers of the
- recipient. Required.
- ]
- }
-
- # JSON input template you can fill out and use as your body input.
- body = notification_content
-
- # response body for status code(s): 202
- response == {
- "receipts": [
- {
- "messageId": "str", # The message id. Required.
- "to": "str" # The native external platform user identifier
- of the recipient. Required.
- }
- ]
- }
"""
@overload
- def send(
- self,
- body: JSON,
- *,
- content_type: str = "application/json",
- **kwargs: Any
- ) -> _models.SendMessageResult:
+ def send(self, body: JSON, *, content_type: str = "application/json", **kwargs: Any) -> _models.SendMessageResult:
"""Sends a notification message from Business to User.
- :param body: Required.
+ :param body: Details of the message to send. Required.
:type body: JSON
:keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
Default value is "application/json".
@@ -288,33 +159,15 @@ def send(
:return: SendMessageResult. The SendMessageResult is compatible with MutableMapping
:rtype: ~azure.communication.messages.models.SendMessageResult
:raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # response body for status code(s): 202
- response == {
- "receipts": [
- {
- "messageId": "str", # The message id. Required.
- "to": "str" # The native external platform user identifier
- of the recipient. Required.
- }
- ]
- }
"""
@overload
def send(
- self,
- body: IO[bytes],
- *,
- content_type: str = "application/json",
- **kwargs: Any
+ self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any
) -> _models.SendMessageResult:
"""Sends a notification message from Business to User.
- :param body: Required.
+ :param body: Details of the message to send. Required.
:type body: IO[bytes]
:keyword content_type: Body Parameter content-type. Content type parameter for binary body.
Default value is "application/json".
@@ -322,148 +175,34 @@ def send(
:return: SendMessageResult. The SendMessageResult is compatible with MutableMapping
:rtype: ~azure.communication.messages.models.SendMessageResult
:raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # response body for status code(s): 202
- response == {
- "receipts": [
- {
- "messageId": "str", # The message id. Required.
- "to": "str" # The native external platform user identifier
- of the recipient. Required.
- }
- ]
- }
"""
-
@distributed_trace
def send(
- self,
- body: Union[_models.NotificationContent, JSON, IO[bytes]],
- **kwargs: Any
+ self, body: Union[_models.NotificationContent, JSON, IO[bytes]], **kwargs: Any
) -> _models.SendMessageResult:
- # pylint: disable=line-too-long
"""Sends a notification message from Business to User.
- :param body: Is one of the following types: NotificationContent, JSON, IO[bytes] Required.
+ :param body: Details of the message to send. Is one of the following types:
+ NotificationContent, JSON, IO[bytes] Required.
:type body: ~azure.communication.messages.models.NotificationContent or JSON or IO[bytes]
:return: SendMessageResult. The SendMessageResult is compatible with MutableMapping
:rtype: ~azure.communication.messages.models.SendMessageResult
:raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # The input is polymorphic. The following are possible polymorphic inputs based off
- discriminator "kind":
-
- # JSON input template for discriminator value "image":
- notification_content = {
- "channelRegistrationId": "str", # The Channel Registration ID for the
- Business Identifier. Required.
- "kind": "image",
- "mediaUri": "str", # A media url for the file. Required if the type is one
- of the supported media types, e.g. image. Required.
- "to": [
- "str" # The native external platform user identifiers of the
- recipient. Required.
- ],
- "content": "str" # Optional. Optional text content.
- }
-
- # JSON input template for discriminator value "template":
- notification_content = {
- "channelRegistrationId": "str", # The Channel Registration ID for the
- Business Identifier. Required.
- "kind": "template",
- "template": {
- "language": "str", # 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.
- "name": "str", # Name of the template. Required.
- "bindings": message_template_bindings,
- "values": [
- message_template_value
- ]
- },
- "to": [
- "str" # The native external platform user identifiers of the
- recipient. Required.
- ]
- }
-
- # JSON input template for discriminator value "whatsApp":
- message_template_bindings = {
- "kind": "whatsApp",
- "body": [
- {
- "refValue": "str" # The name of the referenced item in the
- template values. Required.
- }
- ],
- "buttons": [
- {
- "refValue": "str", # The name of the referenced item in the
- template values. Required.
- "subType": "str" # The WhatsApp button sub type. Required.
- Known values are: "quickReply" and "url".
- }
- ],
- "footer": [
- {
- "refValue": "str" # The name of the referenced item in the
- template values. Required.
- }
- ],
- "header": [
- {
- "refValue": "str" # The name of the referenced item in the
- template values. Required.
- }
- ]
- }
-
- # JSON input template for discriminator value "text":
- notification_content = {
- "channelRegistrationId": "str", # The Channel Registration ID for the
- Business Identifier. Required.
- "content": "str", # Message content. Required.
- "kind": "text",
- "to": [
- "str" # The native external platform user identifiers of the
- recipient. Required.
- ]
- }
-
- # JSON input template you can fill out and use as your body input.
- body = notification_content
-
- # response body for status code(s): 202
- response == {
- "receipts": [
- {
- "messageId": "str", # The message id. Required.
- "to": "str" # The native external platform user identifier
- of the recipient. Required.
- }
- ]
- }
"""
- error_map = {
- 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError, 304: ResourceNotModifiedError
+ error_map: MutableMapping[int, Type[HttpResponseError]] = { # pylint: disable=unsubscriptable-object
+ 401: ClientAuthenticationError,
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
}
- error_map.update(kwargs.pop('error_map', {}) or {})
+ error_map.update(kwargs.pop("error_map", {}) or {})
_headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
_params = kwargs.pop("params", {}) or {}
- content_type: Optional[str] = kwargs.pop('content_type', _headers.pop('Content-Type', None))
- cls: ClsType[_models.SendMessageResult] = kwargs.pop(
- 'cls', None
- )
+ content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
+ cls: ClsType[_models.SendMessageResult] = kwargs.pop("cls", None)
content_type = content_type or "application/json"
_content = None
@@ -480,50 +219,46 @@ def send(
params=_params,
)
path_format_arguments = {
- "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, 'str', skip_quote=True),
+ "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
}
_request.url = self._client.format_url(_request.url, **path_format_arguments)
_stream = kwargs.pop("stream", False)
- pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access
- _request,
- stream=_stream,
- **kwargs
+ pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
)
response = pipeline_response.http_response
if response.status_code not in [202]:
if _stream:
- response.read() # Load the body in memory and close the socket
+ try:
+ response.read() # Load the body in memory and close the socket
+ except (StreamConsumedError, StreamClosedError):
+ pass
map_error(status_code=response.status_code, response=response, error_map=error_map)
raise HttpResponseError(response=response)
response_headers = {}
- response_headers['Repeatability-Result']=self._deserialize('str', response.headers.get('Repeatability-Result'))
- response_headers['x-ms-client-request-id']=self._deserialize('str', response.headers.get('x-ms-client-request-id'))
+ response_headers["Repeatability-Result"] = self._deserialize(
+ "str", response.headers.get("Repeatability-Result")
+ )
+ response_headers["x-ms-client-request-id"] = self._deserialize(
+ "str", response.headers.get("x-ms-client-request-id")
+ )
if _stream:
deserialized = response.iter_bytes()
else:
- deserialized = _deserialize(
- _models.SendMessageResult,
- response.json()
- )
+ deserialized = _deserialize(_models.SendMessageResult, response.json())
if cls:
- return cls(pipeline_response, deserialized, response_headers) # type: ignore
+ return cls(pipeline_response, deserialized, response_headers) # type: ignore
return deserialized # type: ignore
-
-
@distributed_trace
- def download_media(
- self,
- id: str,
- **kwargs: Any
- ) -> Iterator[bytes]:
+ def download_media(self, id: str, **kwargs: Any) -> Iterator[bytes]:
"""Download the Media payload from a User to Business message.
:param id: The stream ID. Required.
@@ -532,20 +267,18 @@ def download_media(
:rtype: Iterator[bytes]
:raises ~azure.core.exceptions.HttpResponseError:
"""
- error_map = {
+ error_map: MutableMapping[int, Type[HttpResponseError]] = { # pylint: disable=unsubscriptable-object
401: ClientAuthenticationError,
404: ResourceNotFoundError,
409: ResourceExistsError,
- 304: ResourceNotModifiedError
+ 304: ResourceNotModifiedError,
}
- error_map.update(kwargs.pop('error_map', {}) or {})
+ error_map.update(kwargs.pop("error_map", {}) or {})
_headers = kwargs.pop("headers", {}) or {}
_params = kwargs.pop("params", {}) or {}
- cls: ClsType[Iterator[bytes]] = kwargs.pop(
- 'cls', None
- )
+ cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None)
_request = build_notification_messages_download_media_request(
id=id,
@@ -554,47 +287,44 @@ def download_media(
params=_params,
)
path_format_arguments = {
- "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, 'str', skip_quote=True),
+ "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
}
_request.url = self._client.format_url(_request.url, **path_format_arguments)
_stream = kwargs.pop("stream", True)
- pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access
- _request,
- stream=_stream,
- **kwargs
+ pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
)
response = pipeline_response.http_response
if response.status_code not in [200]:
if _stream:
- response.read() # Load the body in memory and close the socket
+ try:
+ response.read() # Load the body in memory and close the socket
+ except (StreamConsumedError, StreamClosedError):
+ pass
map_error(status_code=response.status_code, response=response, error_map=error_map)
raise HttpResponseError(response=response)
response_headers = {}
- response_headers['x-ms-client-request-id']=self._deserialize('str',
- response.headers.get('x-ms-client-request-id'))
+ response_headers["x-ms-client-request-id"] = self._deserialize(
+ "str", response.headers.get("x-ms-client-request-id")
+ )
+ response_headers["content-type"] = self._deserialize("str", response.headers.get("content-type"))
deserialized = response.iter_bytes()
if cls:
- return cls(pipeline_response, deserialized, response_headers) # type: ignore
+ return cls(pipeline_response, deserialized, response_headers) # type: ignore
return deserialized # type: ignore
-class MessageTemplateClientOperationsMixin(
- MessageTemplateClientMixinABC
-):
+
+class MessageTemplateClientOperationsMixin(MessageTemplateClientMixinABC):
@distributed_trace
- def list_templates(
- self,
- channel_id: str,
- **kwargs: Any
- ) -> Iterable["_models.MessageTemplateItem"]:
- # pylint: disable=line-too-long
+ def list_templates(self, channel_id: str, **kwargs: Any) -> Iterable["_models.MessageTemplateItem"]:
"""List all templates for given Azure Communication Services channel.
:param channel_id: The registration ID of the channel. Required.
@@ -602,43 +332,24 @@ def list_templates(
:return: An iterator like instance of MessageTemplateItem
:rtype: ~azure.core.paging.ItemPaged[~azure.communication.messages.models.MessageTemplateItem]
:raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # The response is polymorphic. The following are possible polymorphic responses based
- off discriminator "kind":
-
- # JSON input template for discriminator value "whatsApp":
- message_template_item = {
- "kind": "whatsApp",
- "language": "str", # 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.
- "name": "str", # The template's name. Required.
- "status": "str", # The aggregated template status. Required. Known values
- are: "approved", "rejected", "pending", and "paused".
- "content": {} # Optional. WhatsApp platform's template content. This is the
- payload returned from WhatsApp API.
- }
-
- # response body for status code(s): 200
- response == message_template_item
"""
_headers = kwargs.pop("headers", {}) or {}
_params = kwargs.pop("params", {}) or {}
maxpagesize = kwargs.pop("maxpagesize", None)
- cls: ClsType[List[_models.MessageTemplateItem]] = kwargs.pop(
- 'cls', None
- )
+ cls: ClsType[List[_models.MessageTemplateItem]] = kwargs.pop("cls", None)
- error_map = {
- 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError, 304: ResourceNotModifiedError
+ error_map: MutableMapping[int, Type[HttpResponseError]] = { # pylint: disable=unsubscriptable-object
+ 401: ClientAuthenticationError,
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
}
- error_map.update(kwargs.pop('error_map', {}) or {})
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
def prepare_request(next_link=None):
if not next_link:
+
_request = build_message_template_list_templates_request(
channel_id=channel_id,
maxpagesize=maxpagesize,
@@ -647,19 +358,29 @@ def prepare_request(next_link=None):
params=_params,
)
path_format_arguments = {
- "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, 'str', skip_quote=True),
+ "endpoint": self._serialize.url(
+ "self._config.endpoint", self._config.endpoint, "str", skip_quote=True
+ ),
}
_request.url = self._client.format_url(_request.url, **path_format_arguments)
else:
# make call to next link with the client's api-version
_parsed_next_link = urllib.parse.urlparse(next_link)
- _next_request_params = case_insensitive_dict({
- key: [urllib.parse.quote(v) for v in value] for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()})
+ _next_request_params = case_insensitive_dict(
+ {
+ key: [urllib.parse.quote(v) for v in value]
+ for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()
+ }
+ )
_next_request_params["api-version"] = self._config.api_version
- _request = HttpRequest("GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params)
+ _request = HttpRequest(
+ "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params
+ )
path_format_arguments = {
- "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, 'str', skip_quote=True),
+ "endpoint": self._serialize.url(
+ "self._config.endpoint", self._config.endpoint, "str", skip_quote=True
+ ),
}
_request.url = self._client.format_url(_request.url, **path_format_arguments)
@@ -669,29 +390,22 @@ def extract_data(pipeline_response):
deserialized = pipeline_response.http_response.json()
list_of_elem = _deserialize(List[_models.MessageTemplateItem], deserialized["value"])
if cls:
- list_of_elem = cls(list_of_elem) # type: ignore
+ list_of_elem = cls(list_of_elem) # type: ignore
return deserialized.get("nextLink") or None, iter(list_of_elem)
def get_next(next_link=None):
_request = prepare_request(next_link)
_stream = False
- pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access
- _request,
- stream=_stream,
- **kwargs
+ pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access
+ _request, stream=_stream, **kwargs
)
response = pipeline_response.http_response
if response.status_code not in [200]:
- if _stream:
- response.read() # Load the body in memory and close the socket
map_error(status_code=response.status_code, response=response, error_map=error_map)
raise HttpResponseError(response=response)
return pipeline_response
-
- return ItemPaged(
- get_next, extract_data
- )
+ return ItemPaged(get_next, extract_data)
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 acf74720bcfd..eb3162ba82cb 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/_patch.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_patch.py
@@ -6,11 +6,7 @@
Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize
"""
-from typing import (
- List,
- Any,
- Union
-)
+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
@@ -21,6 +17,7 @@
from ._shared.auth_policy_utils import get_authentication_policy
from ._api_versions import DEFAULT_VERSION
+
class NotificationMessagesClient(NotificationMessagesClientGenerated):
"""A client to interact with the AzureCommunicationService Messaging service.
@@ -52,7 +49,7 @@ def __init__(self, endpoint: str, credential: Union[TokenCredential, AzureKeyCre
self._endpoint = endpoint
self._api_version = kwargs.pop("api_version", DEFAULT_VERSION)
- self._authentication_policy = get_authentication_policy(endpoint, credential)
+ self._authentication_policy = get_authentication_policy(endpoint, credential)
self._credential = credential
super().__init__(
self._endpoint,
@@ -61,6 +58,7 @@ def __init__(self, endpoint: str, credential: Union[TokenCredential, AzureKeyCre
api_version=self._api_version,
**kwargs
)
+
@classmethod
def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "NotificationMessagesClient":
"""Create NotificationMessagesClient from a Connection String.
@@ -74,6 +72,7 @@ def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "NotificationMe
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.
@@ -105,12 +104,14 @@ def __init__(self, endpoint: str, credential: Union[TokenCredential, AzureKeyCre
self._endpoint = endpoint
self._api_version = kwargs.pop("api_version", DEFAULT_VERSION)
- self._authentication_policy = get_authentication_policy(endpoint, credential)
+ self._authentication_policy = get_authentication_policy(endpoint, credential)
self._credential = credential
super().__init__(
- self._endpoint, self._credential,
+ self._endpoint,
+ self._credential,
authentication_policy=self._authentication_policy,
- api_version=self._api_version, **kwargs
+ api_version=self._api_version,
+ **kwargs
)
@classmethod
@@ -126,11 +127,13 @@ def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "MessageTemplat
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
+
def patch_sdk():
"""Do not remove from this file.
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 75e26c415d2c..01a226bd7f14 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/_serialization.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_serialization.py
@@ -1,3 +1,4 @@
+# pylint: disable=too-many-lines
# --------------------------------------------------------------------------
#
# Copyright (c) Microsoft Corporation. All rights reserved.
@@ -24,7 +25,6 @@
#
# --------------------------------------------------------------------------
-# pylint: skip-file
# pyright: reportUnnecessaryTypeIgnoreComment=false
from base64 import b64decode, b64encode
@@ -52,7 +52,6 @@
MutableMapping,
Type,
List,
- Mapping,
)
try:
@@ -91,6 +90,8 @@ def deserialize_from_text(cls, data: Optional[Union[AnyStr, IO]], content_type:
:param data: Input, could be bytes or stream (will be decoded with UTF8) or text
:type data: str or bytes or IO
:param str content_type: The content type.
+ :return: The deserialized data.
+ :rtype: object
"""
if hasattr(data, "read"):
# Assume a stream
@@ -112,7 +113,7 @@ def deserialize_from_text(cls, data: Optional[Union[AnyStr, IO]], content_type:
try:
return json.loads(data_as_str)
except ValueError as err:
- raise DeserializationError("JSON is invalid: {}".format(err), err)
+ raise DeserializationError("JSON is invalid: {}".format(err), err) from err
elif "xml" in (content_type or []):
try:
@@ -144,6 +145,8 @@ def _json_attemp(data):
# context otherwise.
_LOGGER.critical("Wasn't XML not JSON, failing")
raise DeserializationError("XML is invalid") from err
+ elif content_type.startswith("text/"):
+ return data_as_str
raise DeserializationError("Cannot deserialize content-type: {}".format(content_type))
@classmethod
@@ -153,6 +156,11 @@ def deserialize_from_http_generics(cls, body_bytes: Optional[Union[AnyStr, IO]],
Use bytes and headers to NOT use any requests/aiohttp or whatever
specific implementation.
Headers will tested for "content-type"
+
+ :param bytes body_bytes: The body of the response.
+ :param dict headers: The headers of the response.
+ :returns: The deserialized data.
+ :rtype: object
"""
# Try to use content-type from headers if available
content_type = None
@@ -182,15 +190,30 @@ class UTC(datetime.tzinfo):
"""Time Zone info for handling UTC"""
def utcoffset(self, dt):
- """UTF offset for UTC is 0."""
+ """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."""
+ """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."""
+ """No daylight saving for UTC.
+
+ :param datetime.datetime dt: The datetime
+ :returns: The daylight saving time
+ :rtype: datetime.timedelta
+ """
return datetime.timedelta(hours=1)
@@ -233,24 +256,26 @@ def __getinitargs__(self):
_FLATTEN = re.compile(r"(? None:
self.additional_properties: Optional[Dict[str, Any]] = {}
- for k in kwargs:
+ for k in kwargs: # pylint: disable=consider-using-dict-items
if k not in self._attribute_map:
_LOGGER.warning("%s is not a known attribute of class %s and will be ignored", k, self.__class__)
elif k in self._validation and self._validation[k].get("readonly", False):
@@ -298,13 +330,23 @@ def __init__(self, **kwargs: Any) -> None:
setattr(self, k, kwargs[k])
def __eq__(self, other: Any) -> bool:
- """Compare objects by comparing all attributes."""
+ """Compare objects by comparing all attributes.
+
+ :param object other: The object to compare
+ :returns: True if objects are equal
+ :rtype: bool
+ """
if isinstance(other, self.__class__):
return self.__dict__ == other.__dict__
return False
def __ne__(self, other: Any) -> bool:
- """Compare objects by comparing all attributes."""
+ """Compare objects by comparing all attributes.
+
+ :param object other: The object to compare
+ :returns: True if objects are not equal
+ :rtype: bool
+ """
return not self.__eq__(other)
def __str__(self) -> str:
@@ -324,7 +366,11 @@ def is_xml_model(cls) -> bool:
@classmethod
def _create_xml_node(cls):
- """Create XML node."""
+ """Create XML node.
+
+ :returns: The XML node
+ :rtype: xml.etree.ElementTree.Element
+ """
try:
xml_map = cls._xml_map # type: ignore
except AttributeError:
@@ -344,14 +390,14 @@ def serialize(self, keep_readonly: bool = False, **kwargs: Any) -> JSON:
:rtype: dict
"""
serializer = Serializer(self._infer_class_models())
- return serializer._serialize(self, keep_readonly=keep_readonly, **kwargs) # type: ignore
+ return serializer._serialize( # type: ignore # pylint: disable=protected-access
+ self, keep_readonly=keep_readonly, **kwargs
+ )
def as_dict(
self,
keep_readonly: bool = True,
- key_transformer: Callable[
- [str, Dict[str, Any], Any], Any
- ] = attribute_transformer,
+ key_transformer: Callable[[str, Dict[str, Any], Any], Any] = attribute_transformer,
**kwargs: Any
) -> JSON:
"""Return a dict that can be serialized using json.dump.
@@ -380,12 +426,15 @@ def my_key_transformer(key, attr_desc, value):
If you want XML serialization, you can pass the kwargs is_xml=True.
+ :param bool keep_readonly: If you want to serialize the readonly attributes
:param function key_transformer: A key transformer function.
:returns: A dict JSON compatible object
:rtype: dict
"""
serializer = Serializer(self._infer_class_models())
- return serializer._serialize(self, key_transformer=key_transformer, keep_readonly=keep_readonly, **kwargs) # type: ignore
+ return serializer._serialize( # type: ignore # pylint: disable=protected-access
+ self, key_transformer=key_transformer, keep_readonly=keep_readonly, **kwargs
+ )
@classmethod
def _infer_class_models(cls):
@@ -395,7 +444,7 @@ def _infer_class_models(cls):
client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
if cls.__name__ not in client_models:
raise ValueError("Not Autorest generated code")
- except Exception:
+ except Exception: # pylint: disable=broad-exception-caught
# Assume it's not Autorest generated (tests?). Add ourselves as dependencies.
client_models = {cls.__name__: cls}
return client_models
@@ -408,6 +457,7 @@ def deserialize(cls: Type[ModelType], data: Any, content_type: Optional[str] = N
: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
"""
deserializer = Deserializer(cls._infer_class_models())
return deserializer(cls.__name__, data, content_type=content_type) # type: ignore
@@ -426,9 +476,11 @@ def from_dict(
and last_rest_key_case_insensitive_extractor)
:param dict data: A dict using RestAPI structure
+ :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
"""
deserializer = Deserializer(cls._infer_class_models())
deserializer.key_extractors = ( # type: ignore
@@ -448,7 +500,7 @@ def _flatten_subtype(cls, key, objects):
return {}
result = dict(cls._subtype_map[key])
for valuetype in cls._subtype_map[key].values():
- result.update(objects[valuetype]._flatten_subtype(key, objects))
+ result.update(objects[valuetype]._flatten_subtype(key, objects)) # pylint: disable=protected-access
return result
@classmethod
@@ -456,6 +508,11 @@ def _classify(cls, response, objects):
"""Check the class _subtype_map for any child classes.
We want to ignore any inherited _subtype_maps.
Remove the polymorphic key from the initial data.
+
+ :param dict response: The initial data
+ :param dict objects: The class objects
+ :returns: The class to be used
+ :rtype: class
"""
for subtype_key in cls.__dict__.get("_subtype_map", {}).keys():
subtype_value = None
@@ -501,11 +558,13 @@ def _decode_attribute_map_key(key):
inside the received data.
:param str key: A key string from the generated code
+ :returns: The decoded key
+ :rtype: str
"""
return key.replace("\\.", ".")
-class Serializer(object):
+class Serializer(object): # pylint: disable=too-many-public-methods
"""Request object model serializer."""
basic_types = {str: "str", int: "int", bool: "bool", float: "float"}
@@ -540,7 +599,7 @@ class Serializer(object):
"multiple": lambda x, y: x % y != 0,
}
- def __init__(self, classes: Optional[Mapping[str, type]]=None):
+ def __init__(self, classes: Optional[Mapping[str, type]] = None):
self.serialize_type = {
"iso-8601": Serializer.serialize_iso,
"rfc-1123": Serializer.serialize_rfc,
@@ -560,13 +619,16 @@ def __init__(self, classes: Optional[Mapping[str, type]]=None):
self.key_transformer = full_restapi_key_transformer
self.client_side_validation = True
- def _serialize(self, target_obj, data_type=None, **kwargs):
+ def _serialize( # pylint: disable=too-many-nested-blocks, too-many-branches, too-many-statements, too-many-locals
+ self, target_obj, data_type=None, **kwargs
+ ):
"""Serialize data into a string according to type.
- :param target_obj: The data to be serialized.
+ :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.
+ :returns: The serialized data.
"""
key_transformer = kwargs.get("key_transformer", self.key_transformer)
keep_readonly = kwargs.get("keep_readonly", False)
@@ -592,12 +654,14 @@ def _serialize(self, target_obj, data_type=None, **kwargs):
serialized = {}
if is_xml_model_serialization:
- serialized = target_obj._create_xml_node()
+ serialized = target_obj._create_xml_node() # pylint: disable=protected-access
try:
- attributes = target_obj._attribute_map
+ attributes = target_obj._attribute_map # pylint: disable=protected-access
for attr, attr_desc in attributes.items():
attr_name = attr
- if not keep_readonly and target_obj._validation.get(attr_name, {}).get("readonly", False):
+ if not keep_readonly and target_obj._validation.get( # pylint: disable=protected-access
+ attr_name, {}
+ ).get("readonly", False):
continue
if attr_name == "additional_properties" and attr_desc["key"] == "":
@@ -633,7 +697,8 @@ def _serialize(self, target_obj, data_type=None, **kwargs):
if isinstance(new_attr, list):
serialized.extend(new_attr) # type: ignore
elif isinstance(new_attr, ET.Element):
- # If the down XML has no XML/Name, we MUST replace the tag with the local tag. But keeping the namespaces.
+ # If the down XML has no XML/Name,
+ # we MUST replace the tag with the local tag. But keeping the namespaces.
if "name" not in getattr(orig_attr, "_xml_map", {}):
splitted_tag = new_attr.tag.split("}")
if len(splitted_tag) == 2: # Namespace
@@ -664,17 +729,17 @@ def _serialize(self, target_obj, data_type=None, **kwargs):
except (AttributeError, KeyError, TypeError) as err:
msg = "Attribute {} in object {} cannot be serialized.\n{}".format(attr_name, class_name, str(target_obj))
raise SerializationError(msg) from err
- else:
- return serialized
+ return serialized
def body(self, data, data_type, **kwargs):
"""Serialize data intended for a request body.
- :param data: The data to be serialized.
+ :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
+ :returns: The serialized request body
"""
# Just in case this is a dict
@@ -703,7 +768,7 @@ def body(self, data, data_type, **kwargs):
attribute_key_case_insensitive_extractor,
last_rest_key_case_insensitive_extractor,
]
- data = deserializer._deserialize(data_type, data)
+ data = deserializer._deserialize(data_type, data) # pylint: disable=protected-access
except DeserializationError as err:
raise SerializationError("Unable to build a model: " + str(err)) from err
@@ -712,9 +777,11 @@ def body(self, data, data_type, **kwargs):
def url(self, name, data, data_type, **kwargs):
"""Serialize data intended for a URL path.
- :param data: The data to be serialized.
+ :param str name: The name of the URL path parameter.
+ :param object data: The data to be serialized.
: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
"""
@@ -728,27 +795,26 @@ def url(self, name, data, data_type, **kwargs):
output = output.replace("{", quote("{")).replace("}", quote("}"))
else:
output = quote(str(output), safe="")
- except SerializationError:
- raise TypeError("{} must be type {}.".format(name, data_type))
- else:
- return output
+ except SerializationError as exc:
+ raise TypeError("{} must be type {}.".format(name, data_type)) from exc
+ return output
def query(self, name, data, data_type, **kwargs):
"""Serialize data intended for a URL query.
- :param data: The data to be serialized.
+ :param str name: The name of the query parameter.
+ :param object data: The data to be serialized.
:param str data_type: The type to be serialized from.
- :keyword bool skip_quote: Whether to skip quote the serialized result.
- Defaults to False.
:rtype: str, list
:raises: TypeError if serialization fails.
:raises: ValueError if data is None
+ :returns: The serialized query parameter
"""
try:
# Treat the list aside, since we don't want to encode the div separator
if data_type.startswith("["):
internal_data_type = data_type[1:-1]
- do_quote = not kwargs.get('skip_quote', False)
+ do_quote = not kwargs.get("skip_quote", False)
return self.serialize_iter(data, internal_data_type, do_quote=do_quote, **kwargs)
# Not a list, regular serialization
@@ -759,19 +825,20 @@ def query(self, name, data, data_type, **kwargs):
output = str(output)
else:
output = quote(str(output), safe="")
- except SerializationError:
- raise TypeError("{} must be type {}.".format(name, data_type))
- else:
- return str(output)
+ except SerializationError as exc:
+ raise TypeError("{} must be type {}.".format(name, data_type)) from exc
+ return str(output)
def header(self, name, data, data_type, **kwargs):
"""Serialize data intended for a request header.
- :param data: The data to be serialized.
+ :param str name: The name of the header.
+ :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
+ :returns: The serialized header
"""
try:
if data_type in ["[str]"]:
@@ -780,21 +847,20 @@ def header(self, name, data, data_type, **kwargs):
output = self.serialize_data(data, data_type, **kwargs)
if data_type == "bool":
output = json.dumps(output)
- except SerializationError:
- raise TypeError("{} must be type {}.".format(name, data_type))
- else:
- return str(output)
+ except SerializationError as exc:
+ raise TypeError("{} must be type {}.".format(name, data_type)) from exc
+ return str(output)
def serialize_data(self, data, data_type, **kwargs):
"""Serialize generic data according to supplied data type.
- :param data: The data to be serialized.
+ :param object data: The data to be serialized.
:param str data_type: The type to be serialized from.
- :param bool required: Whether it's essential that the data not be
- empty or None
: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
"""
if data is None:
raise ValueError("No value for given attribute")
@@ -805,7 +871,7 @@ def serialize_data(self, data, data_type, **kwargs):
if data_type in self.basic_types.values():
return self.serialize_basic(data, data_type, **kwargs)
- elif data_type in self.serialize_type:
+ if data_type in self.serialize_type:
return self.serialize_type[data_type](data, **kwargs)
# If dependencies is empty, try with current data class
@@ -821,11 +887,10 @@ def serialize_data(self, data, data_type, **kwargs):
except (ValueError, TypeError) as err:
msg = "Unable to serialize value: {!r} as type: {!r}."
raise SerializationError(msg.format(data, data_type)) from err
- else:
- return self._serialize(data, **kwargs)
+ return self._serialize(data, **kwargs)
@classmethod
- def _get_custom_serializers(cls, data_type, **kwargs):
+ def _get_custom_serializers(cls, data_type, **kwargs): # pylint: disable=inconsistent-return-statements
custom_serializer = kwargs.get("basic_types_serializers", {}).get(data_type)
if custom_serializer:
return custom_serializer
@@ -841,23 +906,26 @@ def serialize_basic(cls, data, data_type, **kwargs):
- basic_types_serializers dict[str, callable] : If set, use the callable as serializer
- is_xml bool : If set, use xml_basic_types_serializers
- :param data: Object to be serialized.
+ :param obj data: Object to be serialized.
:param str data_type: Type of object in the iterable.
+ :rtype: str, int, float, bool
+ :return: serialized object
"""
custom_serializer = cls._get_custom_serializers(data_type, **kwargs)
if custom_serializer:
return custom_serializer(data)
if data_type == "str":
return cls.serialize_unicode(data)
- return eval(data_type)(data) # nosec
+ return eval(data_type)(data) # nosec # pylint: disable=eval-used
@classmethod
def serialize_unicode(cls, data):
"""Special handling for serializing unicode strings in Py2.
Encode to UTF-8 if unicode, otherwise handle as a str.
- :param data: Object to be serialized.
+ :param str data: Object to be serialized.
:rtype: str
+ :return: serialized object
"""
try: # If I received an enum, return its value
return data.value
@@ -871,8 +939,7 @@ def serialize_unicode(cls, data):
return data
except NameError:
return str(data)
- else:
- return str(data)
+ return str(data)
def serialize_iter(self, data, iter_type, div=None, **kwargs):
"""Serialize iterable.
@@ -882,15 +949,13 @@ def serialize_iter(self, data, iter_type, div=None, **kwargs):
serialization_ctxt['type'] should be same as data_type.
- is_xml bool : If set, serialize as XML
- :param list attr: Object to be serialized.
+ :param list data: Object to be serialized.
:param str iter_type: Type of object in the iterable.
- :param bool required: Whether the objects in the iterable must
- not be None or empty.
:param str div: If set, this str will be used to combine the elements
in the iterable into a combined string. Default is 'None'.
- :keyword bool do_quote: Whether to quote the serialized result of each iterable element.
Defaults to False.
:rtype: list, str
+ :return: serialized iterable
"""
if isinstance(data, str):
raise SerializationError("Refuse str type as a valid iter type.")
@@ -907,12 +972,8 @@ def serialize_iter(self, data, iter_type, div=None, **kwargs):
raise
serialized.append(None)
- if kwargs.get('do_quote', False):
- serialized = [
- '' if s is None else quote(str(s), safe='')
- for s
- in serialized
- ]
+ if kwargs.get("do_quote", False):
+ serialized = ["" if s is None else quote(str(s), safe="") for s in serialized]
if div:
serialized = ["" if s is None else str(s) for s in serialized]
@@ -949,9 +1010,8 @@ def serialize_dict(self, attr, dict_type, **kwargs):
:param dict attr: Object to be serialized.
:param str dict_type: Type of object in the dictionary.
- :param bool required: Whether the objects in the dictionary must
- not be None or empty.
:rtype: dict
+ :return: serialized dictionary
"""
serialization_ctxt = kwargs.get("serialization_ctxt", {})
serialized = {}
@@ -975,7 +1035,7 @@ def serialize_dict(self, attr, dict_type, **kwargs):
return serialized
- def serialize_object(self, attr, **kwargs):
+ def serialize_object(self, attr, **kwargs): # pylint: disable=too-many-return-statements
"""Serialize a generic object.
This will be handled as a dictionary. If object passed in is not
a basic type (str, int, float, dict, list) it will simply be
@@ -983,6 +1043,7 @@ def serialize_object(self, attr, **kwargs):
:param dict attr: Object to be serialized.
:rtype: dict or str
+ :return: serialized object
"""
if attr is None:
return None
@@ -1007,7 +1068,7 @@ def serialize_object(self, attr, **kwargs):
return self.serialize_decimal(attr)
# If it's a model or I know this dependency, serialize as a Model
- elif obj_type in self.dependencies.values() or isinstance(attr, Model):
+ if obj_type in self.dependencies.values() or isinstance(attr, Model):
return self._serialize(attr)
if obj_type == dict:
@@ -1038,56 +1099,61 @@ def serialize_enum(attr, enum_obj=None):
try:
enum_obj(result) # type: ignore
return result
- except ValueError:
+ except ValueError as exc:
for enum_value in enum_obj: # type: ignore
if enum_value.value.lower() == str(attr).lower():
return enum_value.value
error = "{!r} is not valid value for enum {!r}"
- raise SerializationError(error.format(attr, enum_obj))
+ raise SerializationError(error.format(attr, enum_obj)) from exc
@staticmethod
- def serialize_bytearray(attr, **kwargs):
+ def serialize_bytearray(attr, **kwargs): # pylint: disable=unused-argument
"""Serialize bytearray into base-64 string.
- :param attr: Object to be serialized.
+ :param str attr: Object to be serialized.
:rtype: str
+ :return: serialized base64
"""
return b64encode(attr).decode()
@staticmethod
- def serialize_base64(attr, **kwargs):
+ def serialize_base64(attr, **kwargs): # pylint: disable=unused-argument
"""Serialize str into base-64 string.
- :param attr: Object to be serialized.
+ :param str attr: Object to be serialized.
:rtype: str
+ :return: serialized base64
"""
encoded = b64encode(attr).decode("ascii")
return encoded.strip("=").replace("+", "-").replace("/", "_")
@staticmethod
- def serialize_decimal(attr, **kwargs):
+ def serialize_decimal(attr, **kwargs): # pylint: disable=unused-argument
"""Serialize Decimal object to float.
- :param attr: Object to be serialized.
+ :param decimal attr: Object to be serialized.
:rtype: float
+ :return: serialized decimal
"""
return float(attr)
@staticmethod
- def serialize_long(attr, **kwargs):
+ def serialize_long(attr, **kwargs): # pylint: disable=unused-argument
"""Serialize long (Py2) or int (Py3).
- :param attr: Object to be serialized.
+ :param int attr: Object to be serialized.
:rtype: int/long
+ :return: serialized long
"""
return _long_type(attr)
@staticmethod
- def serialize_date(attr, **kwargs):
+ def serialize_date(attr, **kwargs): # pylint: disable=unused-argument
"""Serialize Date object into ISO-8601 formatted string.
:param Date attr: Object to be serialized.
:rtype: str
+ :return: serialized date
"""
if isinstance(attr, str):
attr = isodate.parse_date(attr)
@@ -1095,11 +1161,12 @@ def serialize_date(attr, **kwargs):
return t
@staticmethod
- def serialize_time(attr, **kwargs):
+ def serialize_time(attr, **kwargs): # pylint: disable=unused-argument
"""Serialize Time object into ISO-8601 formatted string.
:param datetime.time attr: Object to be serialized.
:rtype: str
+ :return: serialized time
"""
if isinstance(attr, str):
attr = isodate.parse_time(attr)
@@ -1109,30 +1176,32 @@ def serialize_time(attr, **kwargs):
return t
@staticmethod
- def serialize_duration(attr, **kwargs):
+ def serialize_duration(attr, **kwargs): # pylint: disable=unused-argument
"""Serialize TimeDelta object into ISO-8601 formatted string.
:param TimeDelta attr: Object to be serialized.
:rtype: str
+ :return: serialized duration
"""
if isinstance(attr, str):
attr = isodate.parse_duration(attr)
return isodate.duration_isoformat(attr)
@staticmethod
- def serialize_rfc(attr, **kwargs):
+ def serialize_rfc(attr, **kwargs): # pylint: disable=unused-argument
"""Serialize Datetime object into RFC-1123 formatted string.
:param Datetime attr: Object to be serialized.
:rtype: str
:raises: TypeError if format invalid.
+ :return: serialized rfc
"""
try:
if not attr.tzinfo:
_LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
utc = attr.utctimetuple()
- except AttributeError:
- raise TypeError("RFC1123 object must be valid Datetime object.")
+ except AttributeError as exc:
+ raise TypeError("RFC1123 object must be valid Datetime object.") from exc
return "{}, {:02} {} {:04} {:02}:{:02}:{:02} GMT".format(
Serializer.days[utc.tm_wday],
@@ -1145,12 +1214,13 @@ def serialize_rfc(attr, **kwargs):
)
@staticmethod
- def serialize_iso(attr, **kwargs):
+ def serialize_iso(attr, **kwargs): # pylint: disable=unused-argument
"""Serialize Datetime object into ISO-8601 formatted string.
:param Datetime attr: Object to be serialized.
:rtype: str
:raises: SerializationError if format invalid.
+ :return: serialized iso
"""
if isinstance(attr, str):
attr = isodate.parse_datetime(attr)
@@ -1176,13 +1246,14 @@ def serialize_iso(attr, **kwargs):
raise TypeError(msg) from err
@staticmethod
- def serialize_unix(attr, **kwargs):
+ def serialize_unix(attr, **kwargs): # pylint: disable=unused-argument
"""Serialize Datetime object into IntTime format.
This is represented as seconds.
:param Datetime attr: Object to be serialized.
:rtype: int
:raises: SerializationError if format invalid
+ :return: serialied unix
"""
if isinstance(attr, int):
return attr
@@ -1190,11 +1261,11 @@ def serialize_unix(attr, **kwargs):
if not attr.tzinfo:
_LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
return int(calendar.timegm(attr.utctimetuple()))
- except AttributeError:
- raise TypeError("Unix time object must be valid Datetime object.")
+ except AttributeError as exc:
+ raise TypeError("Unix time object must be valid Datetime object.") from exc
-def rest_key_extractor(attr, attr_desc, data):
+def rest_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
key = attr_desc["key"]
working_data = data
@@ -1215,7 +1286,9 @@ def rest_key_extractor(attr, attr_desc, data):
return working_data.get(key)
-def rest_key_case_insensitive_extractor(attr, attr_desc, data):
+def rest_key_case_insensitive_extractor( # pylint: disable=unused-argument, inconsistent-return-statements
+ attr, attr_desc, data
+):
key = attr_desc["key"]
working_data = data
@@ -1236,17 +1309,29 @@ def rest_key_case_insensitive_extractor(attr, attr_desc, data):
return attribute_key_case_insensitive_extractor(key, None, working_data)
-def last_rest_key_extractor(attr, attr_desc, data):
- """Extract the attribute in "data" based on the last part of the JSON path key."""
+def last_rest_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
+ """Extract the attribute in "data" based on the last part of the JSON path key.
+
+ :param str attr: The attribute to extract
+ :param dict attr_desc: The attribute description
+ :param dict data: The data to extract from
+ :rtype: object
+ :returns: The extracted attribute
+ """
key = attr_desc["key"]
dict_keys = _FLATTEN.split(key)
return attribute_key_extractor(dict_keys[-1], None, data)
-def last_rest_key_case_insensitive_extractor(attr, attr_desc, data):
+def last_rest_key_case_insensitive_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
"""Extract the attribute in "data" based on the last part of the JSON path key.
This is the case insensitive version of "last_rest_key_extractor"
+ :param str attr: The attribute to extract
+ :param dict attr_desc: The attribute description
+ :param dict data: The data to extract from
+ :rtype: object
+ :returns: The extracted attribute
"""
key = attr_desc["key"]
dict_keys = _FLATTEN.split(key)
@@ -1283,7 +1368,7 @@ def _extract_name_from_internal_type(internal_type):
return xml_name
-def xml_key_extractor(attr, attr_desc, data):
+def xml_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument,too-many-return-statements
if isinstance(data, dict):
return None
@@ -1335,22 +1420,21 @@ def xml_key_extractor(attr, attr_desc, data):
if is_iter_type:
if is_wrapped:
return None # is_wrapped no node, we want None
- else:
- return [] # not wrapped, assume empty list
+ return [] # not wrapped, assume empty list
return None # Assume it's not there, maybe an optional node.
# If is_iter_type and not wrapped, return all found children
if is_iter_type:
if not is_wrapped:
return children
- else: # 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(
- xml_name
- )
+ # 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
+ xml_name
)
- return list(children[0]) # Might be empty list and that's ok.
+ )
+ return list(children[0]) # Might be empty list and that's ok.
# Here it's not a itertype, we should have found one element only or empty
if len(children) > 1:
@@ -1367,9 +1451,9 @@ class Deserializer(object):
basic_types = {str: "str", int: "int", bool: "bool", float: "float"}
- valid_date = re.compile(r"\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}" r"\.?\d*Z?[-+]?[\d{2}]?:?[\d{2}]?")
+ valid_date = re.compile(r"\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}\.?\d*Z?[-+]?[\d{2}]?:?[\d{2}]?")
- def __init__(self, classes: Optional[Mapping[str, type]]=None):
+ def __init__(self, classes: Optional[Mapping[str, type]] = None):
self.deserialize_type = {
"iso-8601": Deserializer.deserialize_iso,
"rfc-1123": Deserializer.deserialize_rfc,
@@ -1407,11 +1491,12 @@ def __call__(self, target_obj, response_data, content_type=None):
:param str content_type: Swagger "produces" if available.
:raises: DeserializationError if deserialization fails.
:return: Deserialized object.
+ :rtype: object
"""
data = self._unpack_content(response_data, content_type)
return self._deserialize(target_obj, data)
- def _deserialize(self, target_obj, data):
+ def _deserialize(self, target_obj, data): # pylint: disable=inconsistent-return-statements
"""Call the deserializer on a model.
Data needs to be already deserialized as JSON or XML ElementTree
@@ -1420,12 +1505,13 @@ def _deserialize(self, target_obj, data):
:param object data: Object to deserialize.
:raises: DeserializationError if deserialization fails.
:return: Deserialized object.
+ :rtype: object
"""
# This is already a model, go recursive just in case
if hasattr(data, "_attribute_map"):
constants = [name for name, config in getattr(data, "_validation", {}).items() if config.get("constant")]
try:
- for attr, mapconfig in data._attribute_map.items():
+ for attr, mapconfig in data._attribute_map.items(): # pylint: disable=protected-access
if attr in constants:
continue
value = getattr(data, attr)
@@ -1444,13 +1530,13 @@ def _deserialize(self, target_obj, data):
if isinstance(response, str):
return self.deserialize_data(data, response)
- elif isinstance(response, type) and issubclass(response, Enum):
+ if isinstance(response, type) and issubclass(response, Enum):
return self.deserialize_enum(data, response)
- if data is None:
+ if data is None or data is CoreNull:
return data
try:
- attributes = response._attribute_map # type: ignore
+ attributes = response._attribute_map # type: ignore # pylint: disable=protected-access
d_attrs = {}
for attr, attr_desc in attributes.items():
# Check empty string. If it's not empty, someone has a real "additionalProperties"...
@@ -1480,9 +1566,8 @@ def _deserialize(self, target_obj, data):
except (AttributeError, TypeError, KeyError) as err:
msg = "Unable to deserialize to object: " + class_name # type: ignore
raise DeserializationError(msg) from err
- else:
- additional_properties = self._build_additional_properties(attributes, data)
- return self._instantiate_model(response, d_attrs, additional_properties)
+ additional_properties = self._build_additional_properties(attributes, data)
+ return self._instantiate_model(response, d_attrs, additional_properties)
def _build_additional_properties(self, attribute_map, data):
if not self.additional_properties_detection:
@@ -1509,6 +1594,8 @@ def _classify_target(self, target, data):
:param str target: The target object type to deserialize to.
:param str/dict data: The response data to deserialize.
+ :return: The classified target object and its class name.
+ :rtype: tuple
"""
if target is None:
return None, None
@@ -1520,7 +1607,7 @@ def _classify_target(self, target, data):
return target, target
try:
- target = target._classify(data, self.dependencies) # type: ignore
+ target = target._classify(data, self.dependencies) # type: ignore # pylint: disable=protected-access
except AttributeError:
pass # Target is not a Model, no classify
return target, target.__class__.__name__ # type: ignore
@@ -1535,10 +1622,12 @@ def failsafe_deserialize(self, target_obj, data, content_type=None):
:param str target_obj: The target object type to deserialize to.
:param str/dict data: The response data to deserialize.
:param str content_type: Swagger "produces" if available.
+ :return: Deserialized object.
+ :rtype: object
"""
try:
return self(target_obj, data, content_type=content_type)
- except:
+ except: # pylint: disable=bare-except
_LOGGER.debug(
"Ran into a deserialization error. Ignoring since this is failsafe deserialization", exc_info=True
)
@@ -1556,10 +1645,12 @@ def _unpack_content(raw_data, content_type=None):
If raw_data is something else, bypass all logic and return it directly.
- :param raw_data: Data to be processed.
- :param content_type: How to parse if raw_data is a string/bytes.
+ :param obj raw_data: Data to be processed.
+ :param str content_type: How to parse if raw_data is a string/bytes.
:raises JSONDecodeError: If JSON is requested and parsing is impossible.
:raises UnicodeDecodeError: If bytes is not UTF8
+ :rtype: object
+ :return: Unpacked content.
"""
# Assume this is enough to detect a Pipeline Response without importing it
context = getattr(raw_data, "context", {})
@@ -1583,14 +1674,21 @@ def _unpack_content(raw_data, content_type=None):
def _instantiate_model(self, response, attrs, additional_properties=None):
"""Instantiate a response model passing in deserialized args.
- :param response: The response model class.
- :param d_attrs: The deserialized response attributes.
+ :param Response response: The response model class.
+ :param dict attrs: The deserialized response attributes.
+ :param dict additional_properties: Additional properties to be set.
+ :rtype: Response
+ :return: The instantiated response model.
"""
if callable(response):
subtype = getattr(response, "_subtype_map", {})
try:
- readonly = [k for k, v in response._validation.items() if v.get("readonly")]
- const = [k for k, v in response._validation.items() if v.get("constant")]
+ readonly = [
+ k for k, v in response._validation.items() if v.get("readonly") # pylint: disable=protected-access
+ ]
+ const = [
+ k for k, v in response._validation.items() if v.get("constant") # pylint: disable=protected-access
+ ]
kwargs = {k: v for k, v in attrs.items() if k not in subtype and k not in readonly + const}
response_obj = response(**kwargs)
for attr in readonly:
@@ -1600,7 +1698,7 @@ def _instantiate_model(self, response, attrs, additional_properties=None):
return response_obj
except TypeError as err:
msg = "Unable to deserialize {} into model {}. ".format(kwargs, response) # type: ignore
- raise DeserializationError(msg + str(err))
+ raise DeserializationError(msg + str(err)) from err
else:
try:
for attr, value in attrs.items():
@@ -1609,15 +1707,16 @@ def _instantiate_model(self, response, attrs, additional_properties=None):
except Exception as exp:
msg = "Unable to populate response model. "
msg += "Type: {}, Error: {}".format(type(response), exp)
- raise DeserializationError(msg)
+ raise DeserializationError(msg) from exp
- def deserialize_data(self, data, data_type):
+ def deserialize_data(self, data, data_type): # pylint: disable=too-many-return-statements
"""Process data for deserialization according to data type.
:param str data: The response string to be deserialized.
:param str data_type: The type to deserialize to.
:raises: DeserializationError if deserialization fails.
:return: Deserialized object.
+ :rtype: object
"""
if data is None:
return data
@@ -1631,7 +1730,11 @@ def deserialize_data(self, data, data_type):
if isinstance(data, self.deserialize_expected_types.get(data_type, tuple())):
return data
- is_a_text_parsing_type = lambda x: x not in ["object", "[]", r"{}"]
+ is_a_text_parsing_type = lambda x: x not in [ # pylint: disable=unnecessary-lambda-assignment
+ "object",
+ "[]",
+ r"{}",
+ ]
if isinstance(data, ET.Element) and is_a_text_parsing_type(data_type) and not data.text:
return None
data_val = self.deserialize_type[data_type](data)
@@ -1651,14 +1754,14 @@ def deserialize_data(self, data, data_type):
msg = "Unable to deserialize response data."
msg += " Data: {}, {}".format(data, data_type)
raise DeserializationError(msg) from err
- else:
- return self._deserialize(obj_type, data)
+ return self._deserialize(obj_type, data)
def deserialize_iter(self, attr, iter_type):
"""Deserialize an iterable.
:param list attr: Iterable to be deserialized.
:param str iter_type: The type of object in the iterable.
+ :return: Deserialized iterable.
:rtype: list
"""
if attr is None:
@@ -1675,6 +1778,7 @@ def deserialize_dict(self, attr, dict_type):
:param dict/list attr: Dictionary to be deserialized. Also accepts
a list of key, value pairs.
:param str dict_type: The object type of the items in the dictionary.
+ :return: Deserialized dictionary.
:rtype: dict
"""
if isinstance(attr, list):
@@ -1685,11 +1789,12 @@ def deserialize_dict(self, attr, dict_type):
attr = {el.tag: el.text for el in attr}
return {k: self.deserialize_data(v, dict_type) for k, v in attr.items()}
- def deserialize_object(self, attr, **kwargs):
+ def deserialize_object(self, attr, **kwargs): # pylint: disable=too-many-return-statements
"""Deserialize a generic object.
This will be handled as a dictionary.
:param dict attr: Dictionary to be deserialized.
+ :return: Deserialized object.
:rtype: dict
:raises: TypeError if non-builtin datatype encountered.
"""
@@ -1724,11 +1829,10 @@ def deserialize_object(self, attr, **kwargs):
pass
return deserialized
- else:
- error = "Cannot deserialize generic object with type: "
- raise TypeError(error + str(obj_type))
+ error = "Cannot deserialize generic object with type: "
+ raise TypeError(error + str(obj_type))
- def deserialize_basic(self, attr, data_type):
+ def deserialize_basic(self, attr, data_type): # pylint: disable=too-many-return-statements
"""Deserialize basic builtin data type from string.
Will attempt to convert to str, int, float and bool.
This function will also accept '1', '0', 'true' and 'false' as
@@ -1736,6 +1840,7 @@ def deserialize_basic(self, attr, data_type):
:param str attr: response string to be deserialized.
: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.
"""
@@ -1747,24 +1852,23 @@ def deserialize_basic(self, attr, data_type):
if data_type == "str":
# None or '', node is empty string.
return ""
- else:
- # None or '', node with a strong type is None.
- # Don't try to model "empty bool" or "empty int"
- return None
+ # None or '', node with a strong type is None.
+ # Don't try to model "empty bool" or "empty int"
+ return None
if data_type == "bool":
if attr in [True, False, 1, 0]:
return bool(attr)
- elif isinstance(attr, str):
+ if isinstance(attr, str):
if attr.lower() in ["true", "1"]:
return True
- elif attr.lower() in ["false", "0"]:
+ if attr.lower() in ["false", "0"]:
return False
raise TypeError("Invalid boolean value: {}".format(attr))
if data_type == "str":
return self.deserialize_unicode(attr)
- return eval(data_type)(attr) # nosec
+ return eval(data_type)(attr) # nosec # pylint: disable=eval-used
@staticmethod
def deserialize_unicode(data):
@@ -1772,6 +1876,7 @@ def deserialize_unicode(data):
as a string.
:param str data: response string to be deserialized.
+ :return: Deserialized string.
:rtype: str or unicode
"""
# We might be here because we have an enum modeled as string,
@@ -1785,8 +1890,7 @@ def deserialize_unicode(data):
return data
except NameError:
return str(data)
- else:
- return str(data)
+ return str(data)
@staticmethod
def deserialize_enum(data, enum_obj):
@@ -1798,6 +1902,7 @@ def deserialize_enum(data, enum_obj):
:param str data: Response string to be deserialized. If this value is
None or invalid it will be returned as-is.
:param Enum enum_obj: Enum object to deserialize to.
+ :return: Deserialized enum object.
:rtype: Enum
"""
if isinstance(data, enum_obj) or data is None:
@@ -1808,9 +1913,9 @@ def deserialize_enum(data, enum_obj):
# Workaround. We might consider remove it in the future.
try:
return list(enum_obj.__members__.values())[data]
- except IndexError:
+ except IndexError as exc:
error = "{!r} is not a valid index for enum {!r}"
- raise DeserializationError(error.format(data, enum_obj))
+ raise DeserializationError(error.format(data, enum_obj)) from exc
try:
return enum_obj(str(data))
except ValueError:
@@ -1826,6 +1931,7 @@ def deserialize_bytearray(attr):
"""Deserialize string into bytearray.
:param str attr: response string to be deserialized.
+ :return: Deserialized bytearray
:rtype: bytearray
:raises: TypeError if string format invalid.
"""
@@ -1838,6 +1944,7 @@ def deserialize_base64(attr):
"""Deserialize base64 encoded string into string.
:param str attr: response string to be deserialized.
+ :return: Deserialized base64 string
:rtype: bytearray
:raises: TypeError if string format invalid.
"""
@@ -1853,8 +1960,9 @@ def deserialize_decimal(attr):
"""Deserialize string into Decimal object.
:param str attr: response string to be deserialized.
- :rtype: Decimal
+ :return: Deserialized decimal
:raises: DeserializationError if string format invalid.
+ :rtype: decimal
"""
if isinstance(attr, ET.Element):
attr = attr.text
@@ -1869,6 +1977,7 @@ def deserialize_long(attr):
"""Deserialize string into long (Py2) or int (Py3).
:param str attr: response string to be deserialized.
+ :return: Deserialized int
:rtype: long or int
:raises: ValueError if string format invalid.
"""
@@ -1881,6 +1990,7 @@ def deserialize_duration(attr):
"""Deserialize ISO-8601 formatted string into TimeDelta object.
:param str attr: response string to be deserialized.
+ :return: Deserialized duration
:rtype: TimeDelta
:raises: DeserializationError if string format invalid.
"""
@@ -1891,14 +2001,14 @@ def deserialize_duration(attr):
except (ValueError, OverflowError, AttributeError) as err:
msg = "Cannot deserialize duration object."
raise DeserializationError(msg) from err
- else:
- return duration
+ return duration
@staticmethod
def deserialize_date(attr):
"""Deserialize ISO-8601 formatted string into Date object.
:param str attr: response string to be deserialized.
+ :return: Deserialized date
:rtype: Date
:raises: DeserializationError if string format invalid.
"""
@@ -1914,6 +2024,7 @@ def deserialize_time(attr):
"""Deserialize ISO-8601 formatted string into time object.
:param str attr: response string to be deserialized.
+ :return: Deserialized time
:rtype: datetime.time
:raises: DeserializationError if string format invalid.
"""
@@ -1928,6 +2039,7 @@ def deserialize_rfc(attr):
"""Deserialize RFC-1123 formatted string into Datetime object.
:param str attr: response string to be deserialized.
+ :return: Deserialized RFC datetime
:rtype: Datetime
:raises: DeserializationError if string format invalid.
"""
@@ -1943,14 +2055,14 @@ def deserialize_rfc(attr):
except ValueError as err:
msg = "Cannot deserialize to rfc datetime object."
raise DeserializationError(msg) from err
- else:
- return date_obj
+ return date_obj
@staticmethod
def deserialize_iso(attr):
"""Deserialize ISO-8601 formatted string into Datetime object.
:param str attr: response string to be deserialized.
+ :return: Deserialized ISO datetime
:rtype: Datetime
:raises: DeserializationError if string format invalid.
"""
@@ -1980,8 +2092,7 @@ def deserialize_iso(attr):
except (ValueError, OverflowError, AttributeError) as err:
msg = "Cannot deserialize datetime object."
raise DeserializationError(msg) from err
- else:
- return date_obj
+ return date_obj
@staticmethod
def deserialize_unix(attr):
@@ -1989,6 +2100,7 @@ def deserialize_unix(attr):
This is represented as seconds.
:param int attr: Object to be serialized.
+ :return: Deserialized datetime
:rtype: Datetime
:raises: DeserializationError if format invalid
"""
@@ -2000,5 +2112,4 @@ def deserialize_unix(attr):
except ValueError as err:
msg = "Cannot deserialize to unix datetime object."
raise DeserializationError(msg) from err
- else:
- return date_obj
+ return date_obj
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
index 7b646472045c..43875e1197e5 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/models.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/models.py
@@ -14,8 +14,11 @@ 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)
+ warnings.warn(
+ "MICROSOFT_BOT is deprecated and has been replaced by \
+ MICROSOFT_TEAMS_APP identifier.",
+ DeprecationWarning,
+ )
item = "MICROSOFT_TEAMS_APP"
return super().__getattribute__(item)
@@ -47,14 +50,17 @@ class CommunicationCloudEnvironment(str, Enum, metaclass=CaseInsensitiveEnumMeta
@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."""
@@ -83,12 +89,14 @@ def properties(self) -> Mapping[str, Any]:
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
@@ -116,12 +124,14 @@ def __eq__(self, other):
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
@@ -165,6 +175,7 @@ class UnknownIdentifier:
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]
@@ -188,6 +199,7 @@ def __eq__(self, other):
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
@@ -198,6 +210,7 @@ class MicrosoftTeamsUserProperties(TypedDict):
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
@@ -246,6 +259,7 @@ def _format_raw_id(self, properties: MicrosoftTeamsUserProperties) -> str:
class MicrosoftTeamsAppProperties(TypedDict):
"""Dictionary of properties for a MicrosoftTeamsAppIdentifier."""
+
app_id: str
"""The id of the Microsoft Teams application."""
cloud: Union[CommunicationCloudEnvironment, str]
@@ -254,6 +268,7 @@ class MicrosoftTeamsAppProperties(TypedDict):
class _botbackcompatdict(dict):
"""Backwards compatible properties."""
+
def __getitem__(self, __key: Any) -> Any:
try:
return super().__getitem__(__key)
@@ -267,6 +282,7 @@ def __getitem__(self, __key: Any) -> Any:
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
@@ -282,10 +298,13 @@ def __init__(self, app_id: str, **kwargs: Any) -> None:
: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,
- ))
+ 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)
@@ -323,7 +342,7 @@ def __init__(self, bot_id, **kwargs):
"""
warnings.warn(
"The MicrosoftBotIdentifier is deprecated and has been replaced by MicrosoftTeamsAppIdentifier.",
- DeprecationWarning
+ DeprecationWarning,
)
super().__init__(bot_id, **kwargs)
@@ -339,9 +358,7 @@ def identifier_from_raw_id(raw_id: str) -> CommunicationIdentifier: # pylint: d
:rtype: CommunicationIdentifier
"""
if raw_id.startswith(PHONE_NUMBER_PREFIX):
- return PhoneNumberIdentifier(
- value=raw_id[len(PHONE_NUMBER_PREFIX) :], raw_id=raw_id
- )
+ return PhoneNumberIdentifier(value=raw_id[len(PHONE_NUMBER_PREFIX) :], raw_id=raw_id)
segments = raw_id.split(":", maxsplit=2)
if len(segments) < 3:
@@ -350,9 +367,7 @@ def identifier_from_raw_id(raw_id: str) -> CommunicationIdentifier: # pylint: d
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
- )
+ return MicrosoftTeamsUserIdentifier(user_id=suffix, is_anonymous=True, raw_id=raw_id)
if prefix == TEAMS_USER_PUBLIC_CLOUD_PREFIX:
return MicrosoftTeamsUserIdentifier(
user_id=suffix,
diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_types.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_types.py
index c4a9e104060d..1fe86657cb0f 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/_types.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_types.py
@@ -8,4 +8,5 @@
# --------------------------------------------------------------------------
from typing import Literal
+
RepeatabilityResult = Literal["accepted", "rejected"]
diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_vendor.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_vendor.py
index 69423791b491..ad8505048a22 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/_vendor.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_vendor.py
@@ -16,18 +16,19 @@
from ._serialization import Deserializer, Serializer
-class NotificationMessagesClientMixinABC(
- ABC
-):
+
+class NotificationMessagesClientMixinABC(ABC):
"""DO NOT use this class. It is for internal typing use only."""
+
_client: "PipelineClient"
_config: NotificationMessagesClientConfiguration
_serialize: "Serializer"
_deserialize: "Deserializer"
-class MessageTemplateClientMixinABC(
- ABC
-):
+
+
+class MessageTemplateClientMixinABC(ABC):
"""DO NOT use this class. It is for internal typing use only."""
+
_client: "PipelineClient"
_config: MessageTemplateClientConfiguration
_serialize: "Serializer"
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 83602e6274bc..ed0855dea5e6 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.0.1"
+VERSION = "1.1.0"
diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/__init__.py
index 6d57d158f591..f6f164b43755 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/__init__.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/__init__.py
@@ -15,9 +15,10 @@
except ImportError:
_patch_all = []
from ._patch import patch_sdk as _patch_sdk
+
__all__ = [
- 'NotificationMessagesClient',
- 'MessageTemplateClient',
+ "NotificationMessagesClient",
+ "MessageTemplateClient",
]
__all__.extend([p for p in _patch_all if p not in __all__])
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 1e83e764793a..4aa7832ff659 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
@@ -8,6 +8,7 @@
from copy import deepcopy
from typing import Any, Awaitable, TYPE_CHECKING, Union
+from typing_extensions import Self
from azure.core import AsyncPipelineClient
from azure.core.credentials import AzureKeyCredential
@@ -22,51 +23,54 @@
# pylint: disable=unused-import,ungrouped-imports
from azure.core.credentials_async import AsyncTokenCredential
-class NotificationMessagesClient(NotificationMessagesClientOperationsMixin): # pylint: disable=client-accepts-api-version-keyword
+
+class NotificationMessagesClient(
+ NotificationMessagesClientOperationsMixin
+): # pylint: disable=client-accepts-api-version-keyword
"""NotificationMessagesClient.
:param endpoint: The communication resource, for example
https://my-resource.communication.azure.com. Required.
:type endpoint: str
- :param credential: Credential needed for the client to connect to Azure. Is either a
+ :param credential: Credential used to authenticate requests to the service. Is either a
TokenCredential type or a AzureKeyCredential 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 "2024-02-01".
+ :keyword api_version: The API version to use for this operation. Default value is "2024-08-30".
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
+ self, endpoint: str, credential: Union["AsyncTokenCredential", AzureKeyCredential], **kwargs: Any
) -> None:
- _endpoint = '{endpoint}'
+ _endpoint = "{endpoint}"
self._config = NotificationMessagesClientConfiguration(endpoint=endpoint, credential=credential, **kwargs)
- _policies = kwargs.pop('policies', None)
+ _policies = kwargs.pop("policies", None)
if _policies is None:
- _policies = [policies.RequestIdPolicy(**kwargs),
- self._config.headers_policy,self._config.user_agent_policy,
- self._config.proxy_policy,policies.ContentDecodePolicy(**kwargs),
- self._config.redirect_policy,self._config.retry_policy,self._config.authentication_policy,
- self._config.custom_hook_policy,self._config.logging_policy,
- policies.DistributedTracingPolicy(**kwargs),
- policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None,
- self._config.http_logging_policy]
+ _policies = [
+ policies.RequestIdPolicy(**kwargs),
+ self._config.headers_policy,
+ self._config.user_agent_policy,
+ self._config.proxy_policy,
+ policies.ContentDecodePolicy(**kwargs),
+ self._config.redirect_policy,
+ self._config.retry_policy,
+ self._config.authentication_policy,
+ self._config.custom_hook_policy,
+ self._config.logging_policy,
+ policies.DistributedTracingPolicy(**kwargs),
+ policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None,
+ self._config.http_logging_policy,
+ ]
self._client: AsyncPipelineClient = AsyncPipelineClient(base_url=_endpoint, policies=_policies, **kwargs)
-
self._serialize = Serializer()
self._deserialize = Deserializer()
self._serialize.client_side_validation = False
-
def send_request(
- self,
- request: HttpRequest, *, stream: bool = False,
- **kwargs: Any
+ self, request: HttpRequest, *, stream: bool = False, **kwargs: Any
) -> Awaitable[AsyncHttpResponse]:
"""Runs the network request through the client's chained policies.
@@ -87,7 +91,7 @@ def send_request(
request_copy = deepcopy(request)
path_format_arguments = {
- "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, 'str', skip_quote=True),
+ "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
}
request_copy.url = self._client.format_url(request_copy.url, **path_format_arguments)
@@ -96,57 +100,59 @@ def send_request(
async def close(self) -> None:
await self._client.close()
- async def __aenter__(self) -> "NotificationMessagesClient":
+ async def __aenter__(self) -> Self:
await self._client.__aenter__()
return self
async def __aexit__(self, *exc_details: Any) -> None:
await self._client.__aexit__(*exc_details)
+
+
class MessageTemplateClient(MessageTemplateClientOperationsMixin): # pylint: disable=client-accepts-api-version-keyword
"""MessageTemplateClient.
:param endpoint: The communication resource, for example
https://my-resource.communication.azure.com. Required.
:type endpoint: str
- :param credential: Credential needed for the client to connect to Azure. Is either a
+ :param credential: Credential used to authenticate requests to the service. Is either a
TokenCredential type or a AzureKeyCredential 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 "2024-02-01".
+ :keyword api_version: The API version to use for this operation. Default value is "2024-08-30".
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
+ self, endpoint: str, credential: Union["AsyncTokenCredential", AzureKeyCredential], **kwargs: Any
) -> None:
- _endpoint = '{endpoint}'
+ _endpoint = "{endpoint}"
self._config = MessageTemplateClientConfiguration(endpoint=endpoint, credential=credential, **kwargs)
- _policies = kwargs.pop('policies', None)
+ _policies = kwargs.pop("policies", None)
if _policies is None:
- _policies = [policies.RequestIdPolicy(**kwargs),self._config.headers_policy,
- self._config.user_agent_policy,self._config.proxy_policy,
- policies.ContentDecodePolicy(**kwargs),self._config.redirect_policy,
- self._config.retry_policy,self._config.authentication_policy,
- self._config.custom_hook_policy,self._config.logging_policy,
- policies.DistributedTracingPolicy(**kwargs),
- policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None,
- self._config.http_logging_policy]
+ _policies = [
+ policies.RequestIdPolicy(**kwargs),
+ self._config.headers_policy,
+ self._config.user_agent_policy,
+ self._config.proxy_policy,
+ policies.ContentDecodePolicy(**kwargs),
+ self._config.redirect_policy,
+ self._config.retry_policy,
+ self._config.authentication_policy,
+ self._config.custom_hook_policy,
+ self._config.logging_policy,
+ policies.DistributedTracingPolicy(**kwargs),
+ policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None,
+ self._config.http_logging_policy,
+ ]
self._client: AsyncPipelineClient = AsyncPipelineClient(base_url=_endpoint, policies=_policies, **kwargs)
-
self._serialize = Serializer()
self._deserialize = Deserializer()
self._serialize.client_side_validation = False
-
def send_request(
- self,
- request: HttpRequest, *, stream: bool = False,
- **kwargs: Any
+ self, request: HttpRequest, *, stream: bool = False, **kwargs: Any
) -> Awaitable[AsyncHttpResponse]:
"""Runs the network request through the client's chained policies.
@@ -167,7 +173,7 @@ def send_request(
request_copy = deepcopy(request)
path_format_arguments = {
- "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, 'str', skip_quote=True),
+ "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
}
request_copy.url = self._client.format_url(request_copy.url, **path_format_arguments)
@@ -176,7 +182,7 @@ def send_request(
async def close(self) -> None:
await self._client.close()
- async def __aenter__(self) -> "MessageTemplateClient":
+ async def __aenter__(self) -> Self:
await self._client.__aenter__()
return self
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 5308b452aca6..2e15e3c0079d 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
@@ -18,7 +18,7 @@
from azure.core.credentials_async import AsyncTokenCredential
-class NotificationMessagesClientConfiguration: # pylint: disable=too-many-instance-attributes,name-too-long
+class NotificationMessagesClientConfiguration: # pylint: disable=too-many-instance-attributes,name-too-long
"""Configuration for NotificationMessagesClient.
Note that all parameters used to create this instance are saved as instance
@@ -27,22 +27,19 @@ class NotificationMessagesClientConfiguration: # pylint: disable=too-many-ins
:param endpoint: The communication resource, for example
https://my-resource.communication.azure.com. Required.
:type endpoint: str
- :param credential: Credential needed for the client to connect to Azure. Is either a
+ :param credential: Credential used to authenticate requests to the service. Is either a
TokenCredential type or a AzureKeyCredential 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 "2024-02-01".
+ :keyword api_version: The API version to use for this operation. Default value is "2024-08-30".
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
+ self, endpoint: str, credential: Union["AsyncTokenCredential", AzureKeyCredential], **kwargs: Any
) -> None:
- api_version: str = kwargs.pop('api_version', "2024-02-01")
+ api_version: str = kwargs.pop("api_version", "2024-08-30")
if endpoint is None:
raise ValueError("Parameter 'endpoint' must not be None.")
@@ -52,34 +49,33 @@ def __init__(
self.endpoint = endpoint
self.credential = credential
self.api_version = api_version
- self.credential_scopes = kwargs.pop('credential_scopes', ['https://communication.azure.com/.default'])
- kwargs.setdefault('sdk_moniker', 'communication-messages/{}'.format(VERSION))
+ self.credential_scopes = kwargs.pop("credential_scopes", ["https://communication.azure.com/.default"])
+ kwargs.setdefault("sdk_moniker", "communication-messages/{}".format(VERSION))
self.polling_interval = kwargs.get("polling_interval", 30)
self._configure(**kwargs)
def _infer_policy(self, **kwargs):
- if hasattr(self.credential, 'get_token'):
+ if hasattr(self.credential, "get_token"):
return policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs)
if isinstance(self.credential, AzureKeyCredential):
return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", **kwargs)
raise TypeError(f"Unsupported credential: {self.credential}")
- def _configure(
- self,
- **kwargs: Any
- ) -> None:
- self.user_agent_policy = kwargs.get('user_agent_policy') or policies.UserAgentPolicy(**kwargs)
- self.headers_policy = kwargs.get('headers_policy') or policies.HeadersPolicy(**kwargs)
- self.proxy_policy = kwargs.get('proxy_policy') or policies.ProxyPolicy(**kwargs)
- self.logging_policy = kwargs.get('logging_policy') or policies.NetworkTraceLoggingPolicy(**kwargs)
- self.http_logging_policy = kwargs.get('http_logging_policy') or policies.HttpLoggingPolicy(**kwargs)
- self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs)
- self.redirect_policy = kwargs.get('redirect_policy') or policies.AsyncRedirectPolicy(**kwargs)
- self.retry_policy = kwargs.get('retry_policy') or policies.AsyncRetryPolicy(**kwargs)
- self.authentication_policy = kwargs.get('authentication_policy')
+ def _configure(self, **kwargs: Any) -> None:
+ self.user_agent_policy = kwargs.get("user_agent_policy") or policies.UserAgentPolicy(**kwargs)
+ self.headers_policy = kwargs.get("headers_policy") or policies.HeadersPolicy(**kwargs)
+ self.proxy_policy = kwargs.get("proxy_policy") or policies.ProxyPolicy(**kwargs)
+ self.logging_policy = kwargs.get("logging_policy") or policies.NetworkTraceLoggingPolicy(**kwargs)
+ self.http_logging_policy = kwargs.get("http_logging_policy") or policies.HttpLoggingPolicy(**kwargs)
+ self.custom_hook_policy = kwargs.get("custom_hook_policy") or policies.CustomHookPolicy(**kwargs)
+ self.redirect_policy = kwargs.get("redirect_policy") or policies.AsyncRedirectPolicy(**kwargs)
+ self.retry_policy = kwargs.get("retry_policy") or policies.AsyncRetryPolicy(**kwargs)
+ self.authentication_policy = kwargs.get("authentication_policy")
if self.credential and not self.authentication_policy:
self.authentication_policy = self._infer_policy(**kwargs)
-class MessageTemplateClientConfiguration: # pylint: disable=too-many-instance-attributes,name-too-long
+
+
+class MessageTemplateClientConfiguration: # pylint: disable=too-many-instance-attributes,name-too-long
"""Configuration for MessageTemplateClient.
Note that all parameters used to create this instance are saved as instance
@@ -88,22 +84,19 @@ class MessageTemplateClientConfiguration: # pylint: disable=too-many-instance
:param endpoint: The communication resource, for example
https://my-resource.communication.azure.com. Required.
:type endpoint: str
- :param credential: Credential needed for the client to connect to Azure. Is either a
+ :param credential: Credential used to authenticate requests to the service. Is either a
TokenCredential type or a AzureKeyCredential 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 "2024-02-01".
+ :keyword api_version: The API version to use for this operation. Default value is "2024-08-30".
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
+ self, endpoint: str, credential: Union["AsyncTokenCredential", AzureKeyCredential], **kwargs: Any
) -> None:
- api_version: str = kwargs.pop('api_version', "2024-02-01")
+ api_version: str = kwargs.pop("api_version", "2024-08-30")
if endpoint is None:
raise ValueError("Parameter 'endpoint' must not be None.")
@@ -113,30 +106,27 @@ def __init__(
self.endpoint = endpoint
self.credential = credential
self.api_version = api_version
- self.credential_scopes = kwargs.pop('credential_scopes', ['https://communication.azure.com/.default'])
- kwargs.setdefault('sdk_moniker', 'communication-messages/{}'.format(VERSION))
+ self.credential_scopes = kwargs.pop("credential_scopes", ["https://communication.azure.com/.default"])
+ kwargs.setdefault("sdk_moniker", "communication-messages/{}".format(VERSION))
self.polling_interval = kwargs.get("polling_interval", 30)
self._configure(**kwargs)
def _infer_policy(self, **kwargs):
- if hasattr(self.credential, 'get_token'):
+ if hasattr(self.credential, "get_token"):
return policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs)
if isinstance(self.credential, AzureKeyCredential):
return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", **kwargs)
raise TypeError(f"Unsupported credential: {self.credential}")
- def _configure(
- self,
- **kwargs: Any
- ) -> None:
- self.user_agent_policy = kwargs.get('user_agent_policy') or policies.UserAgentPolicy(**kwargs)
- self.headers_policy = kwargs.get('headers_policy') or policies.HeadersPolicy(**kwargs)
- self.proxy_policy = kwargs.get('proxy_policy') or policies.ProxyPolicy(**kwargs)
- self.logging_policy = kwargs.get('logging_policy') or policies.NetworkTraceLoggingPolicy(**kwargs)
- self.http_logging_policy = kwargs.get('http_logging_policy') or policies.HttpLoggingPolicy(**kwargs)
- self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs)
- self.redirect_policy = kwargs.get('redirect_policy') or policies.AsyncRedirectPolicy(**kwargs)
- self.retry_policy = kwargs.get('retry_policy') or policies.AsyncRetryPolicy(**kwargs)
- self.authentication_policy = kwargs.get('authentication_policy')
+ def _configure(self, **kwargs: Any) -> None:
+ self.user_agent_policy = kwargs.get("user_agent_policy") or policies.UserAgentPolicy(**kwargs)
+ self.headers_policy = kwargs.get("headers_policy") or policies.HeadersPolicy(**kwargs)
+ self.proxy_policy = kwargs.get("proxy_policy") or policies.ProxyPolicy(**kwargs)
+ self.logging_policy = kwargs.get("logging_policy") or policies.NetworkTraceLoggingPolicy(**kwargs)
+ self.http_logging_policy = kwargs.get("http_logging_policy") or policies.HttpLoggingPolicy(**kwargs)
+ self.custom_hook_policy = kwargs.get("custom_hook_policy") or policies.CustomHookPolicy(**kwargs)
+ self.redirect_policy = kwargs.get("redirect_policy") or policies.AsyncRedirectPolicy(**kwargs)
+ self.retry_policy = kwargs.get("retry_policy") or policies.AsyncRetryPolicy(**kwargs)
+ self.authentication_policy = kwargs.get("authentication_policy")
if self.credential and not self.authentication_policy:
self.authentication_policy = self._infer_policy(**kwargs)
diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/__init__.py
index b610e644f4c2..5a3a47e6ff3a 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/__init__.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/__init__.py
@@ -12,9 +12,10 @@
from ._patch import __all__ as _patch_all
from ._patch import * # pylint: disable=unused-wildcard-import
from ._patch import patch_sdk as _patch_sdk
+
__all__ = [
- 'NotificationMessagesClientOperationsMixin',
- 'MessageTemplateClientOperationsMixin',
+ "NotificationMessagesClientOperationsMixin",
+ "MessageTemplateClientOperationsMixin",
]
__all__.extend([p for p in _patch_all if p not in __all__])
_patch_sdk()
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 f754eb60ef33..3ddcda2c51ed 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
@@ -9,16 +9,20 @@
from io import IOBase
import json
import sys
-from typing import Any, AsyncIterable, AsyncIterator, Callable, Dict, IO, List, Optional, TypeVar, Union, overload
+from typing import Any, AsyncIterable, AsyncIterator, Callable, Dict, IO, List, Optional, Type, TypeVar, Union, overload
import urllib.parse
from azure.core.async_paging import AsyncItemPaged, AsyncList
-from azure.core.exceptions import (ClientAuthenticationError,
- HttpResponseError,
- ResourceExistsError,
- ResourceNotFoundError,
- ResourceNotModifiedError,
- map_error)
+from azure.core.exceptions import (
+ ClientAuthenticationError,
+ HttpResponseError,
+ ResourceExistsError,
+ ResourceNotFoundError,
+ ResourceNotModifiedError,
+ StreamClosedError,
+ StreamConsumedError,
+ map_error,
+)
from azure.core.pipeline import PipelineResponse
from azure.core.rest import AsyncHttpResponse, HttpRequest
from azure.core.tracing.decorator import distributed_trace
@@ -27,35 +31,31 @@
from ... import models as _models
from ..._model_base import SdkJSONEncoder, _deserialize
-from ..._operations._operations import (build_message_template_list_templates_request,
- build_notification_messages_download_media_request,
- build_notification_messages_send_request)
+from ..._operations._operations import (
+ build_message_template_list_templates_request,
+ build_notification_messages_download_media_request,
+ build_notification_messages_send_request,
+)
from .._vendor import MessageTemplateClientMixinABC, NotificationMessagesClientMixinABC
if sys.version_info >= (3, 9):
from collections.abc import MutableMapping
else:
from typing import MutableMapping # type: ignore # pylint: disable=ungrouped-imports
-JSON = MutableMapping[str, Any] # pylint: disable=unsubscriptable-object
-T = TypeVar('T')
+JSON = MutableMapping[str, Any] # pylint: disable=unsubscriptable-object
+T = TypeVar("T")
ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]
-class NotificationMessagesClientOperationsMixin( # pylint: disable=name-too-long
- NotificationMessagesClientMixinABC
-):
+
+class NotificationMessagesClientOperationsMixin(NotificationMessagesClientMixinABC): # pylint: disable=name-too-long
@overload
async def send(
- self,
- body: _models.NotificationContent,
- *,
- content_type: str = "application/json",
- **kwargs: Any
+ self, body: _models.NotificationContent, *, content_type: str = "application/json", **kwargs: Any
) -> _models.SendMessageResult:
- # pylint: disable=line-too-long
"""Sends a notification message from Business to User.
- :param body: Required.
+ :param body: Details of the message to send. Required.
:type body: ~azure.communication.messages.models.NotificationContent
:keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
Default value is "application/json".
@@ -63,117 +63,15 @@ async def send(
:return: SendMessageResult. The SendMessageResult is compatible with MutableMapping
:rtype: ~azure.communication.messages.models.SendMessageResult
:raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # The input is polymorphic. The following are possible polymorphic inputs based off
- discriminator "kind":
-
- # JSON input template for discriminator value "image":
- notification_content = {
- "channelRegistrationId": "str", # The Channel Registration ID for the
- Business Identifier. Required.
- "kind": "image",
- "mediaUri": "str", # A media url for the file. Required if the type is one
- of the supported media types, e.g. image. Required.
- "to": [
- "str" # The native external platform user identifiers of the
- recipient. Required.
- ],
- "content": "str" # Optional. Optional text content.
- }
-
- # JSON input template for discriminator value "template":
- notification_content = {
- "channelRegistrationId": "str", # The Channel Registration ID for the
- Business Identifier. Required.
- "kind": "template",
- "template": {
- "language": "str", # 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.
- "name": "str", # Name of the template. Required.
- "bindings": message_template_bindings,
- "values": [
- message_template_value
- ]
- },
- "to": [
- "str" # The native external platform user identifiers of the
- recipient. Required.
- ]
- }
-
- # JSON input template for discriminator value "whatsApp":
- message_template_bindings = {
- "kind": "whatsApp",
- "body": [
- {
- "refValue": "str" # The name of the referenced item in the
- template values. Required.
- }
- ],
- "buttons": [
- {
- "refValue": "str", # The name of the referenced item in the
- template values. Required.
- "subType": "str" # The WhatsApp button sub type. Required.
- Known values are: "quickReply" and "url".
- }
- ],
- "footer": [
- {
- "refValue": "str" # The name of the referenced item in the
- template values. Required.
- }
- ],
- "header": [
- {
- "refValue": "str" # The name of the referenced item in the
- template values. Required.
- }
- ]
- }
-
- # JSON input template for discriminator value "text":
- notification_content = {
- "channelRegistrationId": "str", # The Channel Registration ID for the
- Business Identifier. Required.
- "content": "str", # Message content. Required.
- "kind": "text",
- "to": [
- "str" # The native external platform user identifiers of the
- recipient. Required.
- ]
- }
-
- # JSON input template you can fill out and use as your body input.
- body = notification_content
-
- # response body for status code(s): 202
- response == {
- "receipts": [
- {
- "messageId": "str", # The message id. Required.
- "to": "str" # The native external platform user identifier
- of the recipient. Required.
- }
- ]
- }
"""
@overload
async def send(
- self,
- body: JSON,
- *,
- content_type: str = "application/json",
- **kwargs: Any
+ self, body: JSON, *, content_type: str = "application/json", **kwargs: Any
) -> _models.SendMessageResult:
"""Sends a notification message from Business to User.
- :param body: Required.
+ :param body: Details of the message to send. Required.
:type body: JSON
:keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
Default value is "application/json".
@@ -181,33 +79,15 @@ async def send(
:return: SendMessageResult. The SendMessageResult is compatible with MutableMapping
:rtype: ~azure.communication.messages.models.SendMessageResult
:raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # response body for status code(s): 202
- response == {
- "receipts": [
- {
- "messageId": "str", # The message id. Required.
- "to": "str" # The native external platform user identifier
- of the recipient. Required.
- }
- ]
- }
"""
@overload
async def send(
- self,
- body: IO[bytes],
- *,
- content_type: str = "application/json",
- **kwargs: Any
+ self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any
) -> _models.SendMessageResult:
"""Sends a notification message from Business to User.
- :param body: Required.
+ :param body: Details of the message to send. Required.
:type body: IO[bytes]
:keyword content_type: Body Parameter content-type. Content type parameter for binary body.
Default value is "application/json".
@@ -215,148 +95,34 @@ async def send(
:return: SendMessageResult. The SendMessageResult is compatible with MutableMapping
:rtype: ~azure.communication.messages.models.SendMessageResult
:raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # response body for status code(s): 202
- response == {
- "receipts": [
- {
- "messageId": "str", # The message id. Required.
- "to": "str" # The native external platform user identifier
- of the recipient. Required.
- }
- ]
- }
"""
-
@distributed_trace_async
async def send(
- self,
- body: Union[_models.NotificationContent, JSON, IO[bytes]],
- **kwargs: Any
+ self, body: Union[_models.NotificationContent, JSON, IO[bytes]], **kwargs: Any
) -> _models.SendMessageResult:
- # pylint: disable=line-too-long
"""Sends a notification message from Business to User.
- :param body: Is one of the following types: NotificationContent, JSON, IO[bytes] Required.
+ :param body: Details of the message to send. Is one of the following types:
+ NotificationContent, JSON, IO[bytes] Required.
:type body: ~azure.communication.messages.models.NotificationContent or JSON or IO[bytes]
:return: SendMessageResult. The SendMessageResult is compatible with MutableMapping
:rtype: ~azure.communication.messages.models.SendMessageResult
:raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # The input is polymorphic. The following are possible polymorphic inputs based off
- discriminator "kind":
-
- # JSON input template for discriminator value "image":
- notification_content = {
- "channelRegistrationId": "str", # The Channel Registration ID for the
- Business Identifier. Required.
- "kind": "image",
- "mediaUri": "str", # A media url for the file. Required if the type is one
- of the supported media types, e.g. image. Required.
- "to": [
- "str" # The native external platform user identifiers of the
- recipient. Required.
- ],
- "content": "str" # Optional. Optional text content.
- }
-
- # JSON input template for discriminator value "template":
- notification_content = {
- "channelRegistrationId": "str", # The Channel Registration ID for the
- Business Identifier. Required.
- "kind": "template",
- "template": {
- "language": "str", # 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.
- "name": "str", # Name of the template. Required.
- "bindings": message_template_bindings,
- "values": [
- message_template_value
- ]
- },
- "to": [
- "str" # The native external platform user identifiers of the
- recipient. Required.
- ]
- }
-
- # JSON input template for discriminator value "whatsApp":
- message_template_bindings = {
- "kind": "whatsApp",
- "body": [
- {
- "refValue": "str" # The name of the referenced item in the
- template values. Required.
- }
- ],
- "buttons": [
- {
- "refValue": "str", # The name of the referenced item in the
- template values. Required.
- "subType": "str" # The WhatsApp button sub type. Required.
- Known values are: "quickReply" and "url".
- }
- ],
- "footer": [
- {
- "refValue": "str" # The name of the referenced item in the
- template values. Required.
- }
- ],
- "header": [
- {
- "refValue": "str" # The name of the referenced item in the
- template values. Required.
- }
- ]
- }
-
- # JSON input template for discriminator value "text":
- notification_content = {
- "channelRegistrationId": "str", # The Channel Registration ID for the
- Business Identifier. Required.
- "content": "str", # Message content. Required.
- "kind": "text",
- "to": [
- "str" # The native external platform user identifiers of the
- recipient. Required.
- ]
- }
-
- # JSON input template you can fill out and use as your body input.
- body = notification_content
-
- # response body for status code(s): 202
- response == {
- "receipts": [
- {
- "messageId": "str", # The message id. Required.
- "to": "str" # The native external platform user identifier
- of the recipient. Required.
- }
- ]
- }
"""
- error_map = {
- 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError, 304: ResourceNotModifiedError
+ error_map: MutableMapping[int, Type[HttpResponseError]] = { # pylint: disable=unsubscriptable-object
+ 401: ClientAuthenticationError,
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
}
- error_map.update(kwargs.pop('error_map', {}) or {})
+ error_map.update(kwargs.pop("error_map", {}) or {})
_headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
_params = kwargs.pop("params", {}) or {}
- content_type: Optional[str] = kwargs.pop('content_type', _headers.pop('Content-Type', None))
- cls: ClsType[_models.SendMessageResult] = kwargs.pop(
- 'cls', None
- )
+ content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
+ cls: ClsType[_models.SendMessageResult] = kwargs.pop("cls", None)
content_type = content_type or "application/json"
_content = None
@@ -373,50 +139,46 @@ async def send(
params=_params,
)
path_format_arguments = {
- "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, 'str', skip_quote=True),
+ "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
}
_request.url = self._client.format_url(_request.url, **path_format_arguments)
_stream = kwargs.pop("stream", False)
pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access
- _request,
- stream=_stream,
- **kwargs
+ _request, stream=_stream, **kwargs
)
response = pipeline_response.http_response
if response.status_code not in [202]:
if _stream:
- await response.read() # Load the body in memory and close the socket
+ try:
+ await response.read() # Load the body in memory and close the socket
+ except (StreamConsumedError, StreamClosedError):
+ pass
map_error(status_code=response.status_code, response=response, error_map=error_map)
raise HttpResponseError(response=response)
response_headers = {}
- response_headers['Repeatability-Result']=self._deserialize('str', response.headers.get('Repeatability-Result'))
- response_headers['x-ms-client-request-id']=self._deserialize('str', response.headers.get('x-ms-client-request-id'))
+ response_headers["Repeatability-Result"] = self._deserialize(
+ "str", response.headers.get("Repeatability-Result")
+ )
+ response_headers["x-ms-client-request-id"] = self._deserialize(
+ "str", response.headers.get("x-ms-client-request-id")
+ )
if _stream:
deserialized = response.iter_bytes()
else:
- deserialized = _deserialize(
- _models.SendMessageResult,
- response.json()
- )
+ deserialized = _deserialize(_models.SendMessageResult, response.json())
if cls:
- return cls(pipeline_response, deserialized, response_headers) # type: ignore
+ return cls(pipeline_response, deserialized, response_headers) # type: ignore
return deserialized # type: ignore
-
-
@distributed_trace_async
- async def download_media(
- self,
- id: str,
- **kwargs: Any
- ) -> AsyncIterator[bytes]:
+ async def download_media(self, id: str, **kwargs: Any) -> AsyncIterator[bytes]:
"""Download the Media payload from a User to Business message.
:param id: The stream ID. Required.
@@ -425,20 +187,18 @@ async def download_media(
:rtype: AsyncIterator[bytes]
:raises ~azure.core.exceptions.HttpResponseError:
"""
- error_map = {
+ error_map: MutableMapping[int, Type[HttpResponseError]] = { # pylint: disable=unsubscriptable-object
401: ClientAuthenticationError,
404: ResourceNotFoundError,
409: ResourceExistsError,
- 304: ResourceNotModifiedError
+ 304: ResourceNotModifiedError,
}
- error_map.update(kwargs.pop('error_map', {}) or {})
+ error_map.update(kwargs.pop("error_map", {}) or {})
_headers = kwargs.pop("headers", {}) or {}
_params = kwargs.pop("params", {}) or {}
- cls: ClsType[AsyncIterator[bytes]] = kwargs.pop(
- 'cls', None
- )
+ cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None)
_request = build_notification_messages_download_media_request(
id=id,
@@ -447,47 +207,44 @@ async def download_media(
params=_params,
)
path_format_arguments = {
- "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, 'str', skip_quote=True),
+ "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
}
_request.url = self._client.format_url(_request.url, **path_format_arguments)
_stream = kwargs.pop("stream", True)
pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access
- _request,
- stream=_stream,
- **kwargs
+ _request, stream=_stream, **kwargs
)
response = pipeline_response.http_response
if response.status_code not in [200]:
if _stream:
- await response.read() # Load the body in memory and close the socket
+ try:
+ await response.read() # Load the body in memory and close the socket
+ except (StreamConsumedError, StreamClosedError):
+ pass
map_error(status_code=response.status_code, response=response, error_map=error_map)
raise HttpResponseError(response=response)
response_headers = {}
- response_headers['x-ms-client-request-id']=self._deserialize('str',
- response.headers.get('x-ms-client-request-id'))
+ response_headers["x-ms-client-request-id"] = self._deserialize(
+ "str", response.headers.get("x-ms-client-request-id")
+ )
+ response_headers["content-type"] = self._deserialize("str", response.headers.get("content-type"))
deserialized = response.iter_bytes()
if cls:
- return cls(pipeline_response, deserialized, response_headers) # type: ignore
+ return cls(pipeline_response, deserialized, response_headers) # type: ignore
return deserialized # type: ignore
-class MessageTemplateClientOperationsMixin(
- MessageTemplateClientMixinABC
-):
+
+class MessageTemplateClientOperationsMixin(MessageTemplateClientMixinABC):
@distributed_trace
- def list_templates(
- self,
- channel_id: str,
- **kwargs: Any
- ) -> AsyncIterable["_models.MessageTemplateItem"]:
- # pylint: disable=line-too-long
+ def list_templates(self, channel_id: str, **kwargs: Any) -> AsyncIterable["_models.MessageTemplateItem"]:
"""List all templates for given Azure Communication Services channel.
:param channel_id: The registration ID of the channel. Required.
@@ -496,43 +253,24 @@ def list_templates(
:rtype:
~azure.core.async_paging.AsyncItemPaged[~azure.communication.messages.models.MessageTemplateItem]
:raises ~azure.core.exceptions.HttpResponseError:
-
- Example:
- .. code-block:: python
-
- # The response is polymorphic. The following are possible polymorphic responses based
- off discriminator "kind":
-
- # JSON input template for discriminator value "whatsApp":
- message_template_item = {
- "kind": "whatsApp",
- "language": "str", # 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.
- "name": "str", # The template's name. Required.
- "status": "str", # The aggregated template status. Required. Known values
- are: "approved", "rejected", "pending", and "paused".
- "content": {} # Optional. WhatsApp platform's template content. This is the
- payload returned from WhatsApp API.
- }
-
- # response body for status code(s): 200
- response == message_template_item
"""
_headers = kwargs.pop("headers", {}) or {}
_params = kwargs.pop("params", {}) or {}
maxpagesize = kwargs.pop("maxpagesize", None)
- cls: ClsType[List[_models.MessageTemplateItem]] = kwargs.pop(
- 'cls', None
- )
+ cls: ClsType[List[_models.MessageTemplateItem]] = kwargs.pop("cls", None)
- error_map = {
- 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError, 304: ResourceNotModifiedError
+ error_map: MutableMapping[int, Type[HttpResponseError]] = { # pylint: disable=unsubscriptable-object
+ 401: ClientAuthenticationError,
+ 404: ResourceNotFoundError,
+ 409: ResourceExistsError,
+ 304: ResourceNotModifiedError,
}
- error_map.update(kwargs.pop('error_map', {}) or {})
+ error_map.update(kwargs.pop("error_map", {}) or {})
+
def prepare_request(next_link=None):
if not next_link:
+
_request = build_message_template_list_templates_request(
channel_id=channel_id,
maxpagesize=maxpagesize,
@@ -541,19 +279,29 @@ def prepare_request(next_link=None):
params=_params,
)
path_format_arguments = {
- "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, 'str', skip_quote=True),
+ "endpoint": self._serialize.url(
+ "self._config.endpoint", self._config.endpoint, "str", skip_quote=True
+ ),
}
_request.url = self._client.format_url(_request.url, **path_format_arguments)
else:
# make call to next link with the client's api-version
_parsed_next_link = urllib.parse.urlparse(next_link)
- _next_request_params = case_insensitive_dict({
- key: [urllib.parse.quote(v) for v in value] for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()})
+ _next_request_params = case_insensitive_dict(
+ {
+ key: [urllib.parse.quote(v) for v in value]
+ for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()
+ }
+ )
_next_request_params["api-version"] = self._config.api_version
- _request = HttpRequest("GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params)
+ _request = HttpRequest(
+ "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params
+ )
path_format_arguments = {
- "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, 'str', skip_quote=True),
+ "endpoint": self._serialize.url(
+ "self._config.endpoint", self._config.endpoint, "str", skip_quote=True
+ ),
}
_request.url = self._client.format_url(_request.url, **path_format_arguments)
@@ -563,7 +311,7 @@ async def extract_data(pipeline_response):
deserialized = pipeline_response.http_response.json()
list_of_elem = _deserialize(List[_models.MessageTemplateItem], deserialized["value"])
if cls:
- list_of_elem = cls(list_of_elem) # type: ignore
+ list_of_elem = cls(list_of_elem) # type: ignore
return deserialized.get("nextLink") or None, AsyncList(list_of_elem)
async def get_next(next_link=None):
@@ -571,21 +319,14 @@ async def get_next(next_link=None):
_stream = False
pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access
- _request,
- stream=_stream,
- **kwargs
+ _request, stream=_stream, **kwargs
)
response = pipeline_response.http_response
if response.status_code not in [200]:
- if _stream:
- await response.read() # Load the body in memory and close the socket
map_error(status_code=response.status_code, response=response, error_map=error_map)
raise HttpResponseError(response=response)
return pipeline_response
-
- return AsyncItemPaged(
- get_next, extract_data
- )
+ return AsyncItemPaged(get_next, extract_data)
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 409152840451..d69ae3068ceb 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
@@ -22,6 +22,7 @@
from .._api_versions import DEFAULT_VERSION
from .._shared.auth_policy_utils import get_authentication_policy
+
class NotificationMessagesClient(NotificationMessagesClientGenerated):
"""A client to interact with the AzureCommunicationService Messaging service.
@@ -37,8 +38,9 @@ class NotificationMessagesClient(NotificationMessagesClientGenerated):
Note that overriding this default value may result in unsupported behavior.
"""
- def __init__(self, endpoint: str,
- credential: Union[AsyncTokenCredential, AzureKeyCredential], **kwargs: Any) -> None:
+ def __init__(
+ self, endpoint: str, credential: Union[AsyncTokenCredential, AzureKeyCredential], **kwargs: Any
+ ) -> None:
if not credential:
raise ValueError("credential can not be None")
@@ -54,11 +56,14 @@ def __init__(self, endpoint: str,
self._endpoint = endpoint
self._credential = credential
- self._authentication_policy = get_authentication_policy(endpoint, 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
+ self._endpoint,
+ self._credential,
+ authentication_policy=self._authentication_policy,
+ api_version=self._api_version,
+ **kwargs
)
@classmethod
@@ -73,6 +78,7 @@ def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "NotificationMe
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.
@@ -88,8 +94,9 @@ class MessageTemplateClient(MessageTemplateClientGenerated):
:paramtype api_version: str
"""
- def __init__(self, endpoint: str, credential: Union[AsyncTokenCredential,
- AzureKeyCredential], **kwargs: Any) -> "None":
+ def __init__(
+ self, endpoint: str, credential: Union[AsyncTokenCredential, AzureKeyCredential], **kwargs: Any
+ ) -> "None":
if not credential:
raise ValueError("credential can not be None")
@@ -105,10 +112,11 @@ def __init__(self, endpoint: str, credential: Union[AsyncTokenCredential,
self._endpoint = endpoint
self._credential = credential
- self._authentication_policy = get_authentication_policy(endpoint, credential)
+ self._authentication_policy = get_authentication_policy(endpoint, credential)
self._api_version = kwargs.pop("api_version", DEFAULT_VERSION)
super().__init__(
- self._endpoint, self._credential,
+ self._endpoint,
+ self._credential,
authentication_policy=self._authentication_policy,
api_version=self._api_version,
**kwargs
@@ -126,11 +134,13 @@ def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "MessageTemplat
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
+
def patch_sdk():
"""Do not remove from this file.
diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_vendor.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_vendor.py
index 8181c1e90e24..e5c42048e8a2 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_vendor.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_vendor.py
@@ -16,18 +16,19 @@
from .._serialization import Deserializer, Serializer
-class NotificationMessagesClientMixinABC(
- ABC
-):
+
+class NotificationMessagesClientMixinABC(ABC):
"""DO NOT use this class. It is for internal typing use only."""
+
_client: "AsyncPipelineClient"
_config: NotificationMessagesClientConfiguration
_serialize: "Serializer"
_deserialize: "Deserializer"
-class MessageTemplateClientMixinABC(
- ABC
-):
+
+
+class MessageTemplateClientMixinABC(ABC):
"""DO NOT use this class. It is for internal typing use only."""
+
_client: "AsyncPipelineClient"
_config: MessageTemplateClientConfiguration
_serialize: "Serializer"
diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/models/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/messages/models/__init__.py
index 033c45805634..570a3c9a5efe 100644
--- a/sdk/communication/azure-communication-messages/azure/communication/messages/models/__init__.py
+++ b/sdk/communication/azure-communication-messages/azure/communication/messages/models/__init__.py
@@ -6,6 +6,8 @@
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------
+from ._models import AudioNotificationContent
+from ._models import DocumentNotificationContent
from ._models import ImageNotificationContent
from ._models import MessageReceipt
from ._models import MessageTemplate
@@ -22,6 +24,7 @@
from ._models import SendMessageResult
from ._models import TemplateNotificationContent
from ._models import TextNotificationContent
+from ._models import VideoNotificationContent
from ._models import WhatsAppMessageTemplateBindings
from ._models import WhatsAppMessageTemplateBindingsButton
from ._models import WhatsAppMessageTemplateBindingsComponent
@@ -37,34 +40,38 @@
from ._patch import __all__ as _patch_all
from ._patch import * # pylint: disable=unused-wildcard-import
from ._patch import patch_sdk as _patch_sdk
+
__all__ = [
- 'ImageNotificationContent',
- 'MessageReceipt',
- 'MessageTemplate',
- 'MessageTemplateBindings',
- 'MessageTemplateDocument',
- 'MessageTemplateImage',
- 'MessageTemplateItem',
- 'MessageTemplateLocation',
- 'MessageTemplateQuickAction',
- 'MessageTemplateText',
- 'MessageTemplateValue',
- 'MessageTemplateVideo',
- 'NotificationContent',
- 'SendMessageResult',
- 'TemplateNotificationContent',
- 'TextNotificationContent',
- 'WhatsAppMessageTemplateBindings',
- 'WhatsAppMessageTemplateBindingsButton',
- 'WhatsAppMessageTemplateBindingsComponent',
- 'WhatsAppMessageTemplateItem',
- 'CommunicationMessageKind',
- 'CommunicationMessagesChannel',
- 'MessageTemplateBindingsKind',
- 'MessageTemplateStatus',
- 'MessageTemplateValueKind',
- 'RepeatabilityResult',
- 'WhatsAppMessageButtonSubType',
+ "AudioNotificationContent",
+ "DocumentNotificationContent",
+ "ImageNotificationContent",
+ "MessageReceipt",
+ "MessageTemplate",
+ "MessageTemplateBindings",
+ "MessageTemplateDocument",
+ "MessageTemplateImage",
+ "MessageTemplateItem",
+ "MessageTemplateLocation",
+ "MessageTemplateQuickAction",
+ "MessageTemplateText",
+ "MessageTemplateValue",
+ "MessageTemplateVideo",
+ "NotificationContent",
+ "SendMessageResult",
+ "TemplateNotificationContent",
+ "TextNotificationContent",
+ "VideoNotificationContent",
+ "WhatsAppMessageTemplateBindings",
+ "WhatsAppMessageTemplateBindingsButton",
+ "WhatsAppMessageTemplateBindingsComponent",
+ "WhatsAppMessageTemplateItem",
+ "CommunicationMessageKind",
+ "CommunicationMessagesChannel",
+ "MessageTemplateBindingsKind",
+ "MessageTemplateStatus",
+ "MessageTemplateValueKind",
+ "RepeatabilityResult",
+ "WhatsAppMessageButtonSubType",
]
__all__.extend([p for p in _patch_all if p not in __all__])
_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 ba0b05de2243..bec601169dbf 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
@@ -11,33 +11,41 @@
class CommunicationMessageKind(str, Enum, metaclass=CaseInsensitiveEnumMeta):
- """The type of message. Supports text, image, template.
- """
+ """The type of message."""
TEXT = "text"
"""Text message type."""
IMAGE = "image"
"""Image message type."""
+ IMAGE_V0 = "image_v0"
+ """Image message type. Legacy image type for ``MediaNotificationContent`` which is being
+ deprecated"""
+ DOCUMENT = "document"
+ """Document message type."""
+ VIDEO = "video"
+ """Video message type."""
+ AUDIO = "audio"
+ """Audio message type."""
TEMPLATE = "template"
"""Template message type."""
+
class CommunicationMessagesChannel(str, Enum, metaclass=CaseInsensitiveEnumMeta):
- """The type of the communication messages channel.
- """
+ """The type of the communication messages channel."""
WHATSAPP = "whatsApp"
"""The WhatsApp communication messages channel type."""
+
class MessageTemplateBindingsKind(str, Enum, metaclass=CaseInsensitiveEnumMeta):
- """The type of the message template.
- """
+ """The type of the message template."""
WHATSAPP = "whatsApp"
"""The WhatsApp template type."""
+
class MessageTemplateStatus(str, Enum, metaclass=CaseInsensitiveEnumMeta):
- """The aggregated template status.
- """
+ """The aggregated template status."""
APPROVED = "approved"
"""Message template is approved."""
@@ -48,9 +56,9 @@ class MessageTemplateStatus(str, Enum, metaclass=CaseInsensitiveEnumMeta):
PAUSED = "paused"
"""Message template is paused."""
+
class MessageTemplateValueKind(str, Enum, metaclass=CaseInsensitiveEnumMeta):
- """The type of the template parameter.
- """
+ """The type of the template parameter."""
TEXT = "text"
"""The text template parameter type."""
@@ -65,9 +73,9 @@ class MessageTemplateValueKind(str, Enum, metaclass=CaseInsensitiveEnumMeta):
QUICK_ACTION = "quickAction"
"""The quick action template parameter type."""
+
class RepeatabilityResult(str, Enum, metaclass=CaseInsensitiveEnumMeta):
- """Repeatability Result header options.
- """
+ """Repeatability Result header options."""
ACCEPTED = "accepted"
"""If the request was accepted and the server guarantees that the server state reflects a single
@@ -78,9 +86,9 @@ class RepeatabilityResult(str, Enum, metaclass=CaseInsensitiveEnumMeta):
or because the Repeatability-First-Sent value was outside the range of values held by the
server."""
+
class WhatsAppMessageButtonSubType(str, Enum, metaclass=CaseInsensitiveEnumMeta):
- """The WhatsApp button sub type.
- """
+ """The WhatsApp button sub type."""
QUICK_REPLY = "quickReply"
"""The WhatsApp button sub type is quick reply."""
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 635dfc839741..4e99c2b006fd 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
@@ -11,10 +11,12 @@
from .. import _model_base
from .._model_base import rest_discriminator, rest_field
-from ._enums import (CommunicationMessageKind,
- CommunicationMessagesChannel,
- MessageTemplateBindingsKind,
- MessageTemplateValueKind)
+from ._enums import (
+ CommunicationMessageKind,
+ CommunicationMessagesChannel,
+ MessageTemplateBindingsKind,
+ MessageTemplateValueKind,
+)
if TYPE_CHECKING:
# pylint: disable=unused-import,ungrouped-imports
@@ -25,7 +27,9 @@ class NotificationContent(_model_base.Model):
"""Details of the message to send.
You probably want to use the sub-classes and not this class directly. Known sub-classes are:
- ImageNotificationContent, TemplateNotificationContent, TextNotificationContent
+ AudioNotificationContent, DocumentNotificationContent, ImageNotificationContent,
+ MediaNotificationContent, TemplateNotificationContent, TextNotificationContent,
+ VideoNotificationContent
All required parameters must be populated in order to send to server.
@@ -35,7 +39,7 @@ class NotificationContent(_model_base.Model):
:ivar to: The native external platform user identifiers of the recipient. Required.
:vartype to: list[str]
:ivar kind: The type discriminator describing a notification type. Required. Known values are:
- "text", "image", and "template".
+ "text", "image", "image_v0", "document", "video", "audio", and "template".
:vartype kind: str or ~azure.communication.messages.models.CommunicationMessageKind
"""
@@ -46,8 +50,7 @@ class NotificationContent(_model_base.Model):
"""The native external platform user identifiers of the recipient. Required."""
kind: str = rest_discriminator(name="kind")
"""The type discriminator describing a notification type. Required. Known values are: \"text\",
- \"image\", and \"template\"."""
-
+ \"image\", \"image_v0\", \"document\", \"video\", \"audio\", and \"template\"."""
@overload
def __init__(
@@ -56,8 +59,7 @@ def __init__(
channel_registration_id: str,
to: List[str],
kind: str,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -66,12 +68,108 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, **kwargs)
-class ImageNotificationContent(NotificationContent, discriminator='image'):
- """A request to send a media image notification.
+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
+ :ivar to: The native external platform user identifiers of the recipient. Required.
+ :vartype to: list[str]
+ :ivar kind: Message notification type is audio. Required. Audio message type.
+ :vartype kind: str or ~azure.communication.messages.models.AUDIO
+ :ivar media_uri: A media url for the file. Required if the type is one of the supported media
+ types, e.g. image. Required.
+ :vartype media_uri: str
+ """
+
+ kind: Literal[CommunicationMessageKind.AUDIO] = rest_discriminator(name="kind") # type: ignore
+ """Message notification type is audio. Required. Audio message type."""
+ media_uri: str = rest_field(name="mediaUri")
+ """A media url for the file. Required if the type is one of the supported media types, e.g. image.
+ Required."""
+
+ @overload
+ def __init__(
+ self,
+ *,
+ channel_registration_id: str,
+ to: List[str],
+ media_uri: str,
+ ): ...
+
+ @overload
+ def __init__(self, mapping: Mapping[str, Any]):
+ """
+ :param mapping: raw JSON to initialize the model.
+ :type mapping: Mapping[str, Any]
+ """
+
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
+ super().__init__(*args, kind=CommunicationMessageKind.AUDIO, **kwargs)
+
+
+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
+ :ivar to: The native external platform user identifiers of the recipient. Required.
+ :vartype to: list[str]
+ :ivar kind: Message notification type is image. Required. Document message type.
+ :vartype kind: str or ~azure.communication.messages.models.DOCUMENT
+ :ivar caption: Optional text content.
+ :vartype caption: str
+ :ivar file_name: Optional name for the file.
+ :vartype file_name: str
+ :ivar media_uri: A media url for the file. Required if the type is one of the supported media
+ types, e.g. image. Required.
+ :vartype media_uri: str
+ """
+
+ kind: Literal[CommunicationMessageKind.DOCUMENT] = rest_discriminator(name="kind") # type: ignore
+ """Message notification type is image. Required. Document message type."""
+ caption: Optional[str] = rest_field()
+ """Optional text content."""
+ file_name: Optional[str] = rest_field(name="fileName")
+ """Optional name for the file."""
+ media_uri: str = rest_field(name="mediaUri")
+ """A media url for the file. Required if the type is one of the supported media types, e.g. image.
+ Required."""
+
+ @overload
+ def __init__(
+ self,
+ *,
+ channel_registration_id: str,
+ to: List[str],
+ media_uri: str,
+ caption: Optional[str] = None,
+ file_name: Optional[str] = None,
+ ): ...
+
+ @overload
+ def __init__(self, mapping: Mapping[str, Any]):
+ """
+ :param mapping: raw JSON to initialize the model.
+ :type mapping: Mapping[str, Any]
+ """
+
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
+ super().__init__(*args, kind=CommunicationMessageKind.DOCUMENT, **kwargs)
+
+
+class ImageNotificationContent(NotificationContent, discriminator="image"):
+ """A request to send an image notification.
All required parameters must be populated in order to send to server.
@@ -84,20 +182,19 @@ class ImageNotificationContent(NotificationContent, discriminator='image'):
:vartype kind: str or ~azure.communication.messages.models.IMAGE
:ivar content: Optional text content.
:vartype content: str
- :ivar media_uri: A media url for the image file. Required if the type is one of the supported media
+ :ivar media_uri: A media url for the file. Required if the type is one of the supported media
types, e.g. image. Required.
:vartype media_uri: str
"""
kind: Literal[CommunicationMessageKind.IMAGE] = rest_discriminator(name="kind") # type: ignore
"""Message notification type is image. Required. Image message type."""
- content: Optional[str] = rest_field()
+ content: Optional[str] = rest_field(name="caption")
"""Optional text content."""
media_uri: str = rest_field(name="mediaUri")
"""A media url for the file. Required if the type is one of the supported media types, e.g. image.
Required."""
-
@overload
def __init__(
self,
@@ -106,8 +203,7 @@ def __init__(
to: List[str],
media_uri: str,
content: Optional[str] = None,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -116,14 +212,63 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, kind=CommunicationMessageKind.IMAGE, **kwargs)
+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
+ :ivar to: The native external platform user identifiers of the recipient. Required.
+ :vartype to: list[str]
+ :ivar kind: Message notification type is image. Required. Image message type. Legacy image type
+ for ``MediaNotificationContent`` which is being deprecated
+ :vartype kind: str or ~azure.communication.messages.models.IMAGE_V0
+ :ivar content: Optional text content.
+ :vartype content: str
+ :ivar media_uri: A media url for the file. Required if the type is one of the supported media
+ types, e.g. image. Required.
+ :vartype media_uri: str
+ """
+
+ kind: Literal[CommunicationMessageKind.IMAGE_V0] = rest_discriminator(name="kind") # 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()
+ """Optional text content."""
+ media_uri: str = rest_field(name="mediaUri")
+ """A media url for the file. Required if the type is one of the supported media types, e.g. image.
+ Required."""
+
+ @overload
+ def __init__(
+ self,
+ *,
+ channel_registration_id: str,
+ to: List[str],
+ media_uri: str,
+ content: Optional[str] = None,
+ ): ...
+
+ @overload
+ def __init__(self, mapping: Mapping[str, Any]):
+ """
+ :param mapping: raw JSON to initialize the model.
+ :type mapping: Mapping[str, Any]
+ """
+
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
+ super().__init__(*args, kind=CommunicationMessageKind.IMAGE_V0, **kwargs)
+
+
class MessageReceipt(_model_base.Model):
"""Receipt of the sending one message.
- All required parameters must be populated in order to send to server.
:ivar message_id: The message id. Required.
:vartype message_id: str
@@ -136,15 +281,13 @@ class MessageReceipt(_model_base.Model):
to: str = rest_field()
"""The native external platform user identifier of the recipient. Required."""
-
@overload
def __init__(
self,
*,
message_id: str,
to: str,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -153,7 +296,7 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, **kwargs)
@@ -183,7 +326,6 @@ class MessageTemplate(_model_base.Model):
bindings: Optional["_models.MessageTemplateBindings"] = rest_field()
"""The binding object to link values to the template specific locations."""
-
@overload
def __init__(
self,
@@ -192,8 +334,7 @@ def __init__(
language: str,
template_values: Optional[List["_models.MessageTemplateValue"]] = None,
bindings: Optional["_models.MessageTemplateBindings"] = None,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -202,7 +343,7 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, **kwargs)
@@ -222,14 +363,12 @@ class MessageTemplateBindings(_model_base.Model):
kind: str = rest_discriminator(name="kind")
"""The type discriminator describing a template bindings type. Required. \"whatsApp\""""
-
@overload
def __init__(
self,
*,
kind: str,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -238,7 +377,7 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, **kwargs)
@@ -265,15 +404,13 @@ class MessageTemplateValue(_model_base.Model):
"""The type discriminator describing a template parameter type. Required. Known values are:
\"text\", \"image\", \"document\", \"video\", \"location\", and \"quickAction\"."""
-
@overload
def __init__(
self,
*,
name: str,
kind: str,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -282,11 +419,11 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, **kwargs)
-class MessageTemplateDocument(MessageTemplateValue, discriminator='document'):
+class MessageTemplateDocument(MessageTemplateValue, discriminator="document"):
"""The message template's document value information.
All required parameters must be populated in order to send to server.
@@ -312,7 +449,6 @@ class MessageTemplateDocument(MessageTemplateValue, discriminator='document'):
file_name: Optional[str] = rest_field(name="fileName")
"""The [optional] filename of the media file."""
-
@overload
def __init__(
self,
@@ -321,8 +457,7 @@ def __init__(
url: str,
caption: Optional[str] = None,
file_name: Optional[str] = None,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -331,11 +466,11 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, kind=MessageTemplateValueKind.DOCUMENT, **kwargs)
-class MessageTemplateImage(MessageTemplateValue, discriminator='image'):
+class MessageTemplateImage(MessageTemplateValue, discriminator="image"):
"""The message template's image value information.
All required parameters must be populated in order to send to server.
@@ -361,7 +496,6 @@ class MessageTemplateImage(MessageTemplateValue, discriminator='image'):
file_name: Optional[str] = rest_field(name="fileName")
"""The [optional] filename of the media file."""
-
@overload
def __init__(
self,
@@ -370,8 +504,7 @@ def __init__(
url: str,
caption: Optional[str] = None,
file_name: Optional[str] = None,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -380,9 +513,10 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, kind=MessageTemplateValueKind.IMAGE, **kwargs)
+
class MessageTemplateItem(_model_base.Model):
"""The message template as returned from the service.
@@ -391,7 +525,6 @@ class MessageTemplateItem(_model_base.Model):
Readonly variables are only populated by the server, and will be ignored when sending a request.
- All required parameters must be populated in order to send to server.
:ivar name: The template's name. Required.
:vartype name: str
@@ -417,7 +550,6 @@ class MessageTemplateItem(_model_base.Model):
kind: str = rest_discriminator(name="kind")
"""The type discriminator describing a template type. Required. \"whatsApp\""""
-
@overload
def __init__(
self,
@@ -425,8 +557,7 @@ def __init__(
language: str,
status: Union[str, "_models.MessageTemplateStatus"],
kind: str,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -435,11 +566,11 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, **kwargs)
-class MessageTemplateLocation(MessageTemplateValue, discriminator='location'):
+class MessageTemplateLocation(MessageTemplateValue, discriminator="location"):
"""The message template's location value information.
All required parameters must be populated in order to send to server.
@@ -469,7 +600,6 @@ class MessageTemplateLocation(MessageTemplateValue, discriminator='location'):
longitude: float = rest_field()
"""The longitude of the location. Required."""
-
@overload
def __init__(
self,
@@ -479,8 +609,7 @@ def __init__(
longitude: float,
location_name: Optional[str] = None,
address: Optional[str] = None,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -489,11 +618,11 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, kind=MessageTemplateValueKind.LOCATION, **kwargs)
-class MessageTemplateQuickAction(MessageTemplateValue, discriminator='quickAction'):
+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.
@@ -516,7 +645,6 @@ class MessageTemplateQuickAction(MessageTemplateValue, discriminator='quickActio
payload: Optional[str] = rest_field()
"""The [Optional] quick action payload."""
-
@overload
def __init__(
self,
@@ -524,8 +652,7 @@ def __init__(
name: str,
text: Optional[str] = None,
payload: Optional[str] = None,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -534,11 +661,11 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, kind=MessageTemplateValueKind.QUICK_ACTION, **kwargs)
-class MessageTemplateText(MessageTemplateValue, discriminator='text'):
+class MessageTemplateText(MessageTemplateValue, discriminator="text"):
"""The message template's text value information.
All required parameters must be populated in order to send to server.
@@ -556,15 +683,13 @@ class MessageTemplateText(MessageTemplateValue, discriminator='text'):
text: str = rest_field()
"""The text value. Required."""
-
@overload
def __init__(
self,
*,
name: str,
text: str,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -573,11 +698,11 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, kind=MessageTemplateValueKind.TEXT, **kwargs)
-class MessageTemplateVideo(MessageTemplateValue, discriminator='video'):
+class MessageTemplateVideo(MessageTemplateValue, discriminator="video"):
"""The message template's video value information.
All required parameters must be populated in order to send to server.
@@ -603,7 +728,6 @@ class MessageTemplateVideo(MessageTemplateValue, discriminator='video'):
file_name: Optional[str] = rest_field(name="fileName")
"""The [optional] filename of the media file."""
-
@overload
def __init__(
self,
@@ -612,8 +736,7 @@ def __init__(
url: str,
caption: Optional[str] = None,
file_name: Optional[str] = None,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -622,14 +745,13 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, kind=MessageTemplateValueKind.VIDEO, **kwargs)
class SendMessageResult(_model_base.Model):
"""Result of the send message operation.
- All required parameters must be populated in order to send to server.
:ivar receipts: Receipts of the send message operation. Required.
:vartype receipts: list[~azure.communication.messages.models.MessageReceipt]
@@ -638,14 +760,12 @@ class SendMessageResult(_model_base.Model):
receipts: List["_models.MessageReceipt"] = rest_field()
"""Receipts of the send message operation. Required."""
-
@overload
def __init__(
self,
*,
receipts: List["_models.MessageReceipt"],
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -654,11 +774,11 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, **kwargs)
-class TemplateNotificationContent(NotificationContent, discriminator='template'):
+class TemplateNotificationContent(NotificationContent, discriminator="template"):
"""A request to send a template notification.
All required parameters must be populated in order to send to server.
@@ -679,7 +799,6 @@ class TemplateNotificationContent(NotificationContent, discriminator='template')
template: "_models.MessageTemplate" = rest_field()
"""The template object used to create templates. Required."""
-
@overload
def __init__(
self,
@@ -687,8 +806,7 @@ def __init__(
channel_registration_id: str,
to: List[str],
template: "_models.MessageTemplate",
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -697,11 +815,11 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, kind=CommunicationMessageKind.TEMPLATE, **kwargs)
-class TextNotificationContent(NotificationContent, discriminator='text'):
+class TextNotificationContent(NotificationContent, discriminator="text"):
"""A request to send a text notification.
All required parameters must be populated in order to send to server.
@@ -722,7 +840,6 @@ class TextNotificationContent(NotificationContent, discriminator='text'):
content: str = rest_field()
"""Message content. Required."""
-
@overload
def __init__(
self,
@@ -730,8 +847,7 @@ def __init__(
channel_registration_id: str,
to: List[str],
content: str,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -740,10 +856,59 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, kind=CommunicationMessageKind.TEXT, **kwargs)
-class WhatsAppMessageTemplateBindings(MessageTemplateBindings, discriminator='whatsApp'):
+
+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
+ :ivar to: The native external platform user identifiers of the recipient. Required.
+ :vartype to: list[str]
+ :ivar kind: Message notification type is image. Required. Video message type.
+ :vartype kind: str or ~azure.communication.messages.models.VIDEO
+ :ivar caption: Optional text content.
+ :vartype caption: str
+ :ivar media_uri: A media url for the file. Required if the type is one of the supported media
+ types, e.g. image. Required.
+ :vartype media_uri: str
+ """
+
+ kind: Literal[CommunicationMessageKind.VIDEO] = rest_discriminator(name="kind") # type: ignore
+ """Message notification type is image. Required. Video message type."""
+ caption: Optional[str] = rest_field()
+ """Optional text content."""
+ media_uri: str = rest_field(name="mediaUri")
+ """A media url for the file. Required if the type is one of the supported media types, e.g. image.
+ Required."""
+
+ @overload
+ def __init__(
+ self,
+ *,
+ channel_registration_id: str,
+ to: List[str],
+ media_uri: str,
+ caption: Optional[str] = None,
+ ): ...
+
+ @overload
+ def __init__(self, mapping: Mapping[str, Any]):
+ """
+ :param mapping: raw JSON to initialize the model.
+ :type mapping: Mapping[str, Any]
+ """
+
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
+ super().__init__(*args, kind=CommunicationMessageKind.VIDEO, **kwargs)
+
+
+class WhatsAppMessageTemplateBindings(MessageTemplateBindings, discriminator="whatsApp"):
"""The template bindings for WhatsApp.
All required parameters must be populated in order to send to server.
@@ -775,7 +940,6 @@ class WhatsAppMessageTemplateBindings(MessageTemplateBindings, discriminator='wh
buttons: Optional[List["_models.WhatsAppMessageTemplateBindingsButton"]] = rest_field()
"""The button template bindings."""
-
@overload
def __init__(
self,
@@ -784,8 +948,7 @@ def __init__(
body: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = None,
footer: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = None,
buttons: Optional[List["_models.WhatsAppMessageTemplateBindingsButton"]] = None,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -794,9 +957,10 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, kind=MessageTemplateBindingsKind.WHATSAPP, **kwargs)
+
class WhatsAppMessageTemplateBindingsButton(_model_base.Model):
"""The template bindings component button for WhatsApp.
@@ -814,15 +978,13 @@ class WhatsAppMessageTemplateBindingsButton(_model_base.Model):
ref_value: str = rest_field(name="refValue")
"""The name of the referenced item in the template values. Required."""
-
@overload
def __init__(
self,
*,
sub_type: Union[str, "_models.WhatsAppMessageButtonSubType"],
ref_value: str,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -831,9 +993,10 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, **kwargs)
+
class WhatsAppMessageTemplateBindingsComponent(_model_base.Model):
"""The template bindings component for WhatsApp.
@@ -846,14 +1009,12 @@ class WhatsAppMessageTemplateBindingsComponent(_model_base.Model):
ref_value: str = rest_field(name="refValue")
"""The name of the referenced item in the template values. Required."""
-
@overload
def __init__(
self,
*,
ref_value: str,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -862,15 +1023,15 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, **kwargs)
-class WhatsAppMessageTemplateItem(MessageTemplateItem, discriminator='whatsApp'):
+
+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.
- All required parameters must be populated in order to send to server.
:ivar name: The template's name. Required.
:vartype name: str
@@ -885,7 +1046,7 @@ 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()
@@ -894,7 +1055,6 @@ class WhatsAppMessageTemplateItem(MessageTemplateItem, discriminator='whatsApp')
"""Message template response type is whatsApp. Required. The WhatsApp communication messages
channel type."""
-
@overload
def __init__(
self,
@@ -902,8 +1062,7 @@ def __init__(
language: str,
status: Union[str, "_models.MessageTemplateStatus"],
content: Optional[Any] = None,
- ):
- ...
+ ): ...
@overload
def __init__(self, mapping: Mapping[str, Any]):
@@ -912,5 +1071,5 @@ def __init__(self, mapping: Mapping[str, Any]):
:type mapping: Mapping[str, Any]
"""
- def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless-super-delegation
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=useless-super-delegation
super().__init__(*args, kind=CommunicationMessagesChannel.WHATSAPP, **kwargs)
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 7c8f71b12f51..91e6a1c76abc 100644
--- a/sdk/communication/azure-communication-messages/samples/get_templates_list.py
+++ b/sdk/communication/azure-communication-messages/samples/get_templates_list.py
@@ -25,25 +25,26 @@
sys.path.append("..")
+
class GetTemplatesSample(object):
connection_string = os.getenv("COMMUNICATION_SAMPLES_CONNECTION_STRING")
channel_id = os.getenv("WHATSAPP_CHANNEL_ID")
-
+
def get_templates_list(self):
from azure.communication.messages import MessageTemplateClient
- from azure.communication.messages.models import ( TextNotificationContent )
+ from azure.communication.messages.models import TextNotificationContent
message_template_client = MessageTemplateClient.from_connection_string(self.connection_string)
-
+
# calling send() with whatsapp message details
template_list = message_template_client.list_templates(self.channel_id)
-
+
count_templates = len(list(template_list))
- print("Successfully retrieved {} templates from channel_id {}."
- .format(count_templates, self.channel_id))
+ print("Successfully retrieved {} templates from channel_id {}.".format(count_templates, self.channel_id))
+
-if __name__ == '__main__':
+if __name__ == "__main__":
sample = GetTemplatesSample()
sample.get_templates_list()
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 4114851b5a75..261767c07d80 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
@@ -26,28 +26,30 @@
sys.path.append("..")
+
class GetTemplatesSampleAsync(object):
connection_string = os.getenv("COMMUNICATION_SAMPLES_CONNECTION_STRING")
channel_id = os.getenv("WHATSAPP_CHANNEL_ID")
-
+
async def get_templates_list_async(self):
from azure.communication.messages.aio import MessageTemplateClient
message_template_client = MessageTemplateClient.from_connection_string(self.connection_string)
-
+
# calling send() with whatsapp message details
async with message_template_client:
template_list = message_template_client.list_templates(self.channel_id)
async_list_data = [x async for x in template_list]
count_templates = len(list(async_list_data))
- print("Successfully retrieved {} templates from channel_id {}."
- .format(count_templates, self.channel_id))
+ print("Successfully retrieved {} templates from channel_id {}.".format(count_templates, self.channel_id))
+
async def main():
sample = GetTemplatesSampleAsync()
await sample.get_templates_list_async()
-if __name__ == '__main__':
+
+if __name__ == "__main__":
asyncio.run(main())
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
new file mode 100644
index 000000000000..7c4f11c55082
--- /dev/null
+++ b/sdk/communication/azure-communication-messages/samples/send_audio_notification_messages.py
@@ -0,0 +1,57 @@
+# 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.
+# --------------------------------------------------------------------------
+
+"""
+FILE: send_audio_notification_messages.py
+
+DESCRIPTION:
+ This sample demonstrates sending an Whatsapp audio message from business phone number to a single user. The NotificationMessageClient is
+ authenticated using a connection string.
+USAGE:
+ python send_audio_notification_messages.py
+
+ Set the environment variable with your own value before running the sample:
+ 1) COMMUNICATION_SAMPLES_CONNECTION_STRING - the connection string in your ACS resource
+ 2) RECIPIENT_PHONE_NUMBER - a phone number with Whatsapp capabilities. Use list for recipient phone number.
+ 3) WHATSAPP_CHANNEL_ID - Channel created in Azure portal for Advanced Messaging.
+"""
+
+import os
+import sys
+
+sys.path.append("..")
+
+
+class SendWhatsAppMessageSample(object):
+
+ connection_string: str = os.getenv("COMMUNICATION_SAMPLES_CONNECTION_STRING") # type: ignore
+ phone_number: str = os.getenv("RECIPIENT_PHONE_NUMBER") # type: ignore
+ channel_id: str = os.getenv("WHATSAPP_CHANNEL_ID") # type: ignore
+
+ def send_audio_message(self):
+
+ from azure.communication.messages import NotificationMessagesClient
+ from azure.communication.messages.models import AudioNotificationContent
+
+ messaging_client = NotificationMessagesClient.from_connection_string(self.connection_string)
+
+ audio_options = AudioNotificationContent(
+ channel_registration_id=self.channel_id,
+ to=[self.phone_number],
+ media_uri="https://filesamples.com/samples/audio/mp3/sample3.mp3",
+ )
+
+ # calling send() with whatsapp message details
+ message_responses = messaging_client.send(audio_options)
+ response = message_responses.receipts[0]
+ print("Message with message id {} was successful sent to {}".format(response.message_id, response.to))
+
+
+if __name__ == "__main__":
+ sample = SendWhatsAppMessageSample()
+ sample.send_audio_message()
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
new file mode 100644
index 000000000000..847a8d2a08fb
--- /dev/null
+++ b/sdk/communication/azure-communication-messages/samples/send_document_notification_messages.py
@@ -0,0 +1,59 @@
+# 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.
+# --------------------------------------------------------------------------
+
+"""
+FILE: send_document_notification_messages.py
+
+DESCRIPTION:
+ This sample demonstrates sending an Whatsapp message from business phone number to a single user. The NotificationMessageClient is
+ authenticated using a connection string.
+USAGE:
+ python send_document_notification_messages.py
+
+ Set the environment variable with your own value before running the sample:
+ 1) COMMUNICATION_SAMPLES_CONNECTION_STRING - the connection string in your ACS resource
+ 2) RECIPIENT_PHONE_NUMBER - a phone number with Whatsapp capabilities. Use list for recipient phone number.
+ 3) WHATSAPP_CHANNEL_ID - Channel created in Azure portal for Advanced Messaging.
+"""
+
+import os
+import sys
+
+sys.path.append("..")
+
+
+class SendWhatsAppMessageSample(object):
+
+ connection_string: str = os.getenv("COMMUNICATION_SAMPLES_CONNECTION_STRING") # type: ignore
+ phone_number: str = os.getenv("RECIPIENT_PHONE_NUMBER") # type: ignore
+ channel_id: str = os.getenv("WHATSAPP_CHANNEL_ID") # type: ignore
+
+ def send_document_message(self):
+
+ from azure.communication.messages import NotificationMessagesClient
+ from azure.communication.messages.models import DocumentNotificationContent
+
+ messaging_client = NotificationMessagesClient.from_connection_string(self.connection_string)
+
+ text_options = DocumentNotificationContent(
+ channel_registration_id=self.channel_id,
+ to=[self.phone_number],
+ caption="Hello World via Advanced Messaging SDK.This is document message",
+ file_name="Product roadmap timeline.pptx",
+ media_uri="https://sample-videos.com/ppt/Sample-PPT-File-500kb.ppt",
+ )
+
+ # calling send() with whatsapp message details
+ message_responses = messaging_client.send(text_options)
+ response = message_responses.receipts[0]
+ print("Message with message id {} was successful sent to {}".format(response.message_id, response.to))
+
+
+if __name__ == "__main__":
+ sample = SendWhatsAppMessageSample()
+ sample.send_document_message()
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 5f2b10fd0f08..dcf813287188 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
@@ -26,12 +26,13 @@
sys.path.append("..")
+
class SendWhatsAppMessageSample(object):
connection_string = os.getenv("COMMUNICATION_SAMPLES_CONNECTION_STRING")
phone_number = os.getenv("RECIPIENT_PHONE_NUMBER")
channel_id = os.getenv("WHATSAPP_CHANNEL_ID")
-
+
def send_image_send_message(self):
from azure.communication.messages import NotificationMessagesClient
@@ -41,17 +42,17 @@ def send_image_send_message(self):
image_options = ImageNotificationContent(
channel_registration_id=self.channel_id,
- to=[self.phone_number],
+ to=[self.phone_number],
content="Hello World via Notification Messaging SDK.",
- media_uri="https://aka.ms/acsicon1"
+ media_uri="https://aka.ms/acsicon1",
)
-
+
# calling send() with whatsapp message details
message_responses = messaging_client.send(image_options)
response = message_responses.receipts[0]
- print("Message with message id {} was successful sent to {}"
- .format(response.message_id, response.to))
+ print("Message with message id {} was successful sent to {}".format(response.message_id, response.to))
+
-if __name__ == '__main__':
+if __name__ == "__main__":
sample = SendWhatsAppMessageSample()
sample.send_image_send_message()
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 e1260c87e171..df8f4a72e18f 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
@@ -28,12 +28,13 @@
sys.path.append("..")
+
class SendWhatsAppMessageSampleAsync(object):
connection_string = os.getenv("COMMUNICATION_SAMPLES_CONNECTION_STRING")
phone_number = os.getenv("RECIPIENT_PHONE_NUMBER")
channel_id = os.getenv("WHATSAPP_CHANNEL_ID")
-
+
async def send_image_send_message_async(self):
from azure.communication.messages.aio import NotificationMessagesClient
from azure.communication.messages.models import ImageNotificationContent
@@ -43,22 +44,22 @@ async def send_image_send_message_async(self):
image_options = ImageNotificationContent(
channel_registration_id=self.channel_id,
- to= [self.phone_number],
+ to=[self.phone_number],
content="Hello World via Notification Messaging SDK.",
- media_uri="https://aka.ms/acsicon1"
+ media_uri="https://aka.ms/acsicon1",
)
-
+
# calling send() with whatsapp message details
async with messaging_client:
message_responses = await messaging_client.send(image_options)
response = message_responses.receipts[0]
- print("Message with message id {} was successful sent to {}"
- .format(response.message_id, response.to))
+ print("Message with message id {} was successful sent to {}".format(response.message_id, response.to))
+
async def main():
sample = SendWhatsAppMessageSampleAsync()
await sample.send_image_send_message_async()
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
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 cc96ca387ccc..7819ece7ac98 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
@@ -28,12 +28,13 @@
sys.path.append("..")
+
class SendWhatsAppTemplateMessageSample(object):
connection_string = os.getenv("COMMUNICATION_SAMPLES_CONNECTION_STRING")
phone_number = os.getenv("RECIPIENT_PHONE_NUMBER")
channel_id = os.getenv("WHATSAPP_CHANNEL_ID")
-
+
def send_template_send_message(self):
from azure.communication.messages import NotificationMessagesClient
@@ -43,19 +44,18 @@ def send_template_send_message(self):
# Setting template options
input_template: MessageTemplate = MessageTemplate(
- name="gathering_invitation", # Name of the WhatsApp Template
- language="ca") # Language of the WhatsApp Template
+ name="gathering_invitation", language="ca" # Name of the WhatsApp Template
+ ) # Language of the WhatsApp Template
template_options = TemplateNotificationContent(
- channel_registration_id= self.channel_id,
- to=[self.phone_number],
- template=input_template)
-
+ channel_registration_id=self.channel_id, to=[self.phone_number], template=input_template
+ )
+
# calling send() with whatsapp message details
message_responses = messaging_client.send(template_options)
response = message_responses.receipts[0]
- print("Message with message id {} was successful sent to {}"
- .format(response.message_id, response.to))
+ print("Message with message id {} was successful sent to {}".format(response.message_id, response.to))
+
-if __name__ == '__main__':
+if __name__ == "__main__":
sample = SendWhatsAppTemplateMessageSample()
sample.send_template_send_message()
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 43412257e225..d3d2d4d26874 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
@@ -29,12 +29,13 @@
sys.path.append("..")
+
class SendWhatsAppTemplateMessageSampleAsync(object):
connection_string = os.getenv("COMMUNICATION_SAMPLES_CONNECTION_STRING")
phone_number = os.getenv("RECIPIENT_PHONE_NUMBER")
channel_id = os.getenv("WHATSAPP_CHANNEL_ID")
-
+
async def send_template_send_message_async(self):
from azure.communication.messages.aio import NotificationMessagesClient
from azure.communication.messages.models import TemplateNotificationContent, MessageTemplate
@@ -43,24 +44,23 @@ async def send_template_send_message_async(self):
# Setting template options
input_template: MessageTemplate = MessageTemplate(
- name="gathering_invitation", # Name of the WhatsApp Template
- language="ca") # Language of the WhatsApp Template
+ name="gathering_invitation", language="ca" # Name of the WhatsApp Template
+ ) # Language of the WhatsApp Template
template_options = TemplateNotificationContent(
- channel_registration_id= self.channel_id,
- to=[self.phone_number],
- template=input_template)
-
+ channel_registration_id=self.channel_id, to=[self.phone_number], template=input_template
+ )
+
# calling send() with whatsapp message details
async with messaging_client:
- message_responses =await messaging_client.send(template_options)
+ message_responses = await messaging_client.send(template_options)
response = message_responses.receipts[0]
- print("Message with message id {} was successful sent to {}"
- .format(response.message_id, response.to))
+ print("Message with message id {} was successful sent to {}".format(response.message_id, response.to))
async def main():
sample = SendWhatsAppTemplateMessageSampleAsync()
await sample.send_template_send_message_async()
-if __name__ == '__main__':
+
+if __name__ == "__main__":
asyncio.run(main())
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 cb229b4e3fab..390ae2f5d28b 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
@@ -26,12 +26,13 @@
sys.path.append("..")
+
class SendWhatsAppMessageSample(object):
connection_string = os.getenv("COMMUNICATION_SAMPLES_CONNECTION_STRING")
phone_number = os.getenv("RECIPIENT_PHONE_NUMBER")
channel_id = os.getenv("WHATSAPP_CHANNEL_ID")
-
+
def send_text_send_message(self):
from azure.communication.messages import NotificationMessagesClient
@@ -41,16 +42,16 @@ def send_text_send_message(self):
text_options = TextNotificationContent(
channel_registration_id=self.channel_id,
- to=[self.phone_number],
+ to=[self.phone_number],
content="Hello World via Notification Messaging SDK.",
)
-
+
# calling send() with whatsapp message details
message_responses = messaging_client.send(text_options)
response = message_responses.receipts[0]
- print("Message with message id {} was successful sent to {}"
- .format(response.message_id, response.to))
+ print("Message with message id {} was successful sent to {}".format(response.message_id, response.to))
+
-if __name__ == '__main__':
+if __name__ == "__main__":
sample = SendWhatsAppMessageSample()
sample.send_text_send_message()
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 3669995e623a..5b7cdfe4d88d 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
@@ -28,12 +28,13 @@
sys.path.append("..")
+
class SendWhatsAppMessageSampleAsync(object):
connection_string = os.getenv("COMMUNICATION_SAMPLES_CONNECTION_STRING")
phone_number = os.getenv("RECIPIENT_PHONE_NUMBER")
channel_id = os.getenv("WHATSAPP_CHANNEL_ID")
-
+
async def send_text_send_message_async(self):
from azure.communication.messages.aio import NotificationMessagesClient
from azure.communication.messages.models import TextNotificationContent
@@ -46,13 +47,12 @@ async def send_text_send_message_async(self):
to=[self.phone_number],
content="Hello World via Notification Messaging SDK.",
)
-
+
# calling send() with whatsapp message details
async with messaging_client:
message_responses = await messaging_client.send(text_options)
response = message_responses.receipts[0]
- print("Message with message id {} was successful sent to {}"
- .format(response.message_id, response.to))
+ print("Message with message id {} was successful sent to {}".format(response.message_id, response.to))
async def main():
@@ -60,5 +60,5 @@ async def main():
await sample.send_text_send_message_async()
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
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 0e67babf40a7..4f61bec2136e 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
@@ -34,33 +34,35 @@
sys.path.append("..")
+
class SendWhatsAppMessageSample(object):
endpoint_string = os.getenv("COMMUNICATION_SAMPLES_ENDPOINT_STRING")
phone_number = os.getenv("RECIPIENT_PHONE_NUMBER")
channel_id = os.getenv("WHATSAPP_CHANNEL_ID")
-
+
def send_text_send_message(self):
from azure.communication.messages import NotificationMessagesClient
from azure.communication.messages.models import TextNotificationContent
from azure.identity import DefaultAzureCredential
- messaging_client = NotificationMessagesClient(endpoint=self.endpoint_string,
- credential=DefaultAzureCredential())
+ messaging_client = NotificationMessagesClient(
+ endpoint=self.endpoint_string, credential=DefaultAzureCredential()
+ )
text_options = TextNotificationContent(
channel_registration_id=self.channel_id,
- to=[self.phone_number],
+ to=[self.phone_number],
content="Hello World via Notification Messaging SDK using Token credentials.",
)
-
+
# calling send() with whatsapp message details
message_responses = messaging_client.send(text_options)
response = message_responses.receipts[0]
- print("Message with message id {} was successful sent to {}"
- .format(response.message_id, response.to))
+ print("Message with message id {} was successful sent to {}".format(response.message_id, response.to))
+
-if __name__ == '__main__':
+if __name__ == "__main__":
sample = SendWhatsAppMessageSample()
sample.send_text_send_message()
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
new file mode 100644
index 000000000000..96d697ac81db
--- /dev/null
+++ b/sdk/communication/azure-communication-messages/samples/send_video_notification_messages.py
@@ -0,0 +1,57 @@
+# 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.
+# --------------------------------------------------------------------------
+
+"""
+FILE: send_video_notification_messages.py
+
+DESCRIPTION:
+ This sample demonstrates sending an Whatsapp message from business phone number to a single user. The NotificationMessageClient is
+ authenticated using a connection string.
+USAGE:
+ python send_video_notification_messages.py
+
+ Set the environment variable with your own value before running the sample:
+ 1) COMMUNICATION_SAMPLES_CONNECTION_STRING - the connection string in your ACS resource
+ 2) RECIPIENT_PHONE_NUMBER - a phone number with Whatsapp capabilities. Use list for recipient phone number.
+ 3) WHATSAPP_CHANNEL_ID - Channel created in Azure portal for Advanced Messaging.
+"""
+
+import os
+import sys
+
+sys.path.append("..")
+
+
+class SendWhatsAppMessageSample(object):
+
+ connection_string: str = os.getenv("COMMUNICATION_SAMPLES_CONNECTION_STRING") # type: ignore
+ phone_number: str = os.getenv("RECIPIENT_PHONE_NUMBER") # type: ignore
+ channel_id: str = os.getenv("WHATSAPP_CHANNEL_ID") # type: ignore
+
+ def send_video_message(self):
+
+ from azure.communication.messages import NotificationMessagesClient
+ from azure.communication.messages.models import VideoNotificationContent
+
+ messaging_client = NotificationMessagesClient.from_connection_string(self.connection_string)
+
+ video_options = VideoNotificationContent(
+ channel_registration_id=self.channel_id,
+ to=[self.phone_number],
+ media_uri="https://filesamples.com/samples/video/3gp/sample_640x360.3gp",
+ )
+
+ # calling send() with whatsapp message details
+ message_responses = messaging_client.send(video_options)
+ response = message_responses.receipts[0]
+ print("Message with message id {} was successful sent to {}".format(response.message_id, response.to))
+
+
+if __name__ == "__main__":
+ sample = SendWhatsAppMessageSample()
+ sample.send_video_message()
diff --git a/sdk/communication/azure-communication-messages/setup.py b/sdk/communication/azure-communication-messages/setup.py
index 7429140abb45..c0d6b48794c6 100644
--- a/sdk/communication/azure-communication-messages/setup.py
+++ b/sdk/communication/azure-communication-messages/setup.py
@@ -63,8 +63,8 @@
"azure.communication.messages": ["py.typed"],
},
install_requires=[
- "isodate<1.0.0,>=0.6.1",
- "azure-core<2.0.0,>=1.30.0",
+ "isodate>=0.6.1",
+ "azure-core>=1.30.0",
"typing-extensions>=4.6.0",
],
python_requires=">=3.8",
diff --git a/sdk/communication/azure-communication-messages/tests/_decorators.py b/sdk/communication/azure-communication-messages/tests/_decorators.py
index aadf9f57f154..b03a05540dd6 100644
--- a/sdk/communication/azure-communication-messages/tests/_decorators.py
+++ b/sdk/communication/azure-communication-messages/tests/_decorators.py
@@ -10,6 +10,7 @@
from devtools_testutils import is_live, is_live_and_not_recording, trim_kwargs_from_test_function
from azure.communication.messages._shared.utils import parse_connection_str
+
class MessagesPreparers(object):
@staticmethod
@@ -21,10 +22,11 @@ def wrapper(self, *args, **kwargs):
self.resource_name = endpoint.split(".")[0]
else:
- self.connection_string = "endpoint=https://sanitized.unitedstates.communication.azure.com/;accesskey=fake==="
+ self.connection_string = (
+ "endpoint=https://sanitized.unitedstates.communication.azure.com/;accesskey=fake==="
+ )
self.resource_name = "sanitized"
func(self, *args, **kwargs)
return wrapper
-
diff --git a/sdk/communication/azure-communication-messages/tests/_decorators_async.py b/sdk/communication/azure-communication-messages/tests/_decorators_async.py
index c7514f1ed993..3776cabeb288 100644
--- a/sdk/communication/azure-communication-messages/tests/_decorators_async.py
+++ b/sdk/communication/azure-communication-messages/tests/_decorators_async.py
@@ -10,6 +10,7 @@
from devtools_testutils import is_live, is_live_and_not_recording, trim_kwargs_from_test_function
from azure.communication.messages._shared.utils import parse_connection_str
+
class MessagesPreparersAsync(object):
@staticmethod
@@ -21,13 +22,15 @@ async def wrapper(self, *args, **kwargs):
self.resource_name = endpoint.split(".")[0]
else:
- self.connection_string = "endpoint=https://sanitized.unitedstates.communication.azure.com/;accesskey=fake==="
+ self.connection_string = (
+ "endpoint=https://sanitized.unitedstates.communication.azure.com/;accesskey=fake==="
+ )
self.resource_name = "sanitized"
return await func(self, *args, **kwargs)
return wrapper
-
+
@staticmethod
def messages_test_decorator_for_token_async(func: Callable[[], object], **kwargs: Any):
async def wrapper(self, *args, **kwargs):
diff --git a/sdk/communication/azure-communication-messages/tests/_messages_test_case.py b/sdk/communication/azure-communication-messages/tests/_messages_test_case.py
index dfcaa01dc616..998bfd2bf618 100644
--- a/sdk/communication/azure-communication-messages/tests/_messages_test_case.py
+++ b/sdk/communication/azure-communication-messages/tests/_messages_test_case.py
@@ -12,13 +12,14 @@
)
from devtools_testutils import AzureRecordedTestCase
+
class MessagesRecordedTestCase(AzureRecordedTestCase):
def create_notification_message_client(self) -> NotificationMessagesClient:
return NotificationMessagesClient.from_connection_string(
conn_str=self.connection_string, http_logging_policy=get_http_logging_policy()
)
-
+
def create_notification_message_client_from_token(self) -> NotificationMessagesClient:
return NotificationMessagesClient.from_token_credentials(
endpoint=self.endpoint_str, http_logging_policy=get_http_logging_policy()
@@ -28,8 +29,8 @@ def create_message_template_client(self) -> MessageTemplateClient:
return MessageTemplateClient.from_connection_string(
conn_str=self.connection_string, http_logging_policy=get_http_logging_policy()
)
-
+
def create_message_template_client_from_token(self) -> MessageTemplateClient:
return MessageTemplateClient.from_token_credentials(
endpoint=self.endpoint_str, http_logging_policy=get_http_logging_policy()
- )
\ No newline at end of file
+ )
diff --git a/sdk/communication/azure-communication-messages/tests/_messages_test_case_async.py b/sdk/communication/azure-communication-messages/tests/_messages_test_case_async.py
index 5951f64a48bf..384e26ba468c 100644
--- a/sdk/communication/azure-communication-messages/tests/_messages_test_case_async.py
+++ b/sdk/communication/azure-communication-messages/tests/_messages_test_case_async.py
@@ -13,13 +13,14 @@
)
from devtools_testutils import AzureRecordedTestCase
+
class AsyncMessagesRecordedTestCase(AzureRecordedTestCase):
def create_notification_message_client(self) -> NotificationMessagesClient:
return NotificationMessagesClient.from_connection_string(
conn_str=self.connection_string, http_logging_policy=get_http_logging_policy()
)
-
+
def create_notification_message_client_from_token(self) -> NotificationMessagesClient:
return NotificationMessagesClient.from_token_credentials(
endpoint=self.endpoint_str, http_logging_policy=get_http_logging_policy()
@@ -29,8 +30,8 @@ def create_message_template_client(self) -> MessageTemplateClient:
return MessageTemplateClient.from_connection_string(
conn_str=self.connection_string, http_logging_policy=get_http_logging_policy()
)
-
+
def create_message_template_client_from_token(self) -> MessageTemplateClient:
return MessageTemplateClient.from_token_credentials(
endpoint=self.endpoint_str, http_logging_policy=get_http_logging_policy()
- )
\ No newline at end of file
+ )
diff --git a/sdk/communication/azure-communication-messages/tests/_shared/utils.py b/sdk/communication/azure-communication-messages/tests/_shared/utils.py
index 536e680d8fed..ea71205f0e7a 100644
--- a/sdk/communication/azure-communication-messages/tests/_shared/utils.py
+++ b/sdk/communication/azure-communication-messages/tests/_shared/utils.py
@@ -54,7 +54,7 @@ def get_header_policy(**kwargs):
return header_policy
-def parse_connection_str(conn_str:str) -> Tuple[str, str]:
+def parse_connection_str(conn_str: str) -> Tuple[str, str]:
if conn_str is None:
raise ValueError("Connection string is undefined.")
endpoint = None
diff --git a/sdk/communication/azure-communication-messages/tests/conftest.py b/sdk/communication/azure-communication-messages/tests/conftest.py
index e3524c0d8e35..bd0a6705d628 100644
--- a/sdk/communication/azure-communication-messages/tests/conftest.py
+++ b/sdk/communication/azure-communication-messages/tests/conftest.py
@@ -34,25 +34,27 @@
add_body_key_sanitizer,
add_oauth_response_sanitizer,
add_general_string_sanitizer,
- add_general_regex_sanitizer)
+ add_general_regex_sanitizer,
+)
from azure.communication.messages._shared.utils import parse_connection_str
+
# autouse=True will trigger this fixture on each pytest run, even if it's not explicitly used by a test method
@pytest.fixture(scope="session", autouse=True)
def start_proxy(test_proxy):
set_default_session_settings()
add_oauth_response_sanitizer()
-
+
FAKE_CONNECTION_STRING = "endpoint=https://sanitized.unitedstates.communication.azure.com/;accesskey=fake==="
FAKE_ENDPOINT = "sanitized.unitedstates.communication.azure.com"
- connection_str = os.environ.get('COMMUNICATION_LIVETEST_DYNAMIC_CONNECTION_STRING', FAKE_CONNECTION_STRING)
+ connection_str = os.environ.get("COMMUNICATION_LIVETEST_DYNAMIC_CONNECTION_STRING", FAKE_CONNECTION_STRING)
if connection_str is not None:
endpoint, _ = parse_connection_str(connection_str)
resource_name = endpoint.split(".")[0]
add_general_string_sanitizer(target=resource_name, value="sanitized")
add_general_regex_sanitizer(regex=connection_str, value=FAKE_CONNECTION_STRING)
add_general_regex_sanitizer(regex=endpoint, value=FAKE_ENDPOINT)
-
+
add_general_string_sanitizer(target="8f8c29b2-c2e4-4340-bb28-3009c8a57283", value="sanitized")
add_body_key_sanitizer(json_path="channel_registration_id", value="sanitized")
add_body_key_sanitizer(json_path="*.channel_registration_id", value="sanitized")
@@ -76,7 +78,6 @@ def start_proxy(test_proxy):
add_body_key_sanitizer(json_path="*.repeatability-first-sent", value="sanitized")
add_body_key_sanitizer(json_path="*..repeatability-first-sent", value="sanitized")
-
add_header_regex_sanitizer(key="P3P", value="sanitized")
add_header_regex_sanitizer(key="Set-Cookie", value="sanitized")
add_header_regex_sanitizer(key="Date", value="sanitized")
@@ -92,4 +93,4 @@ def start_proxy(test_proxy):
add_header_regex_sanitizer(key="Content-Security-Policy-Report-Only", value="sanitized")
add_header_regex_sanitizer(key="repeatability-first-sent", value="sanitized")
add_header_regex_sanitizer(key="repeatability-request-id", value="sanitized")
- return
\ No newline at end of file
+ return
diff --git a/sdk/communication/azure-communication-messages/tests/test_messages_client.py b/sdk/communication/azure-communication-messages/tests/test_messages_client.py
index fdb7c6ef037b..d288f9a6f77e 100644
--- a/sdk/communication/azure-communication-messages/tests/test_messages_client.py
+++ b/sdk/communication/azure-communication-messages/tests/test_messages_client.py
@@ -20,26 +20,28 @@
MessageTemplateBindings,
MessageTemplateValue,
WhatsAppMessageTemplateBindings,
- WhatsAppMessageTemplateBindingsComponent
- )
+ WhatsAppMessageTemplateBindingsComponent,
+)
from _shared.utils import get_http_logging_policy
from _messages_test_case import MessagesRecordedTestCase
from azure.communication.messages._shared.utils import parse_connection_str
-
+
+
class TestNotificationMessageClientForText(MessagesRecordedTestCase):
@MessagesPreparers.messages_test_decorator
- @recorded_by_proxy
+ @recorded_by_proxy
def test_text_send_message(self):
phone_number: str = "+14254360097"
raised = False
text_options = TextNotificationContent(
channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959",
- to= [phone_number],
- content="Thanks for your feedback Hello.")
+ to=[phone_number],
+ content="Thanks for your feedback Hello.",
+ )
- message_response : MessageReceipt = None
+ message_response: MessageReceipt = None
message_client: NotificationMessagesClient = self.create_notification_message_client()
try:
@@ -53,24 +55,20 @@ def test_text_send_message(self):
assert message_response.message_id is not None
assert message_response.to is not None
-
@MessagesPreparers.messages_test_decorator
- @recorded_by_proxy
+ @recorded_by_proxy
def test_template_send_message(self):
phone_number: str = "+14254360097"
- input_template: MessageTemplate = MessageTemplate(
- name="gathering_invitation",
- language="ca")
+ input_template: MessageTemplate = MessageTemplate(name="pythontest", language="en_US")
raised = False
message_client: NotificationMessagesClient = self.create_notification_message_client()
template_options = TemplateNotificationContent(
- channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959",
- to=[phone_number],
- template=input_template)
+ channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959", to=[phone_number], template=input_template
+ )
- message_response : MessageReceipt = None
+ message_response: MessageReceipt = None
try:
with message_client:
@@ -82,35 +80,29 @@ def test_template_send_message(self):
assert raised is False
assert message_response.message_id is not None
assert message_response.to is not None
-
@MessagesPreparers.messages_test_decorator
- @recorded_by_proxy
+ @recorded_by_proxy
def test_template_with_parameters_send_message(self):
-
+
phone_number: str = "+14254360097"
- parammeter1 = MessageTemplateText (
- name="first",
- text="11-18-2024"
- )
+ parammeter1 = MessageTemplateText(name="first", text="2")
input_template: MessageTemplate = MessageTemplate(
- name="gathering_invitation",
+ name="sample_shipping_confirmation",
language="en_US",
- template_values= [parammeter1],
- bindings=WhatsAppMessageTemplateBindings
- (
- body= [ WhatsAppMessageTemplateBindingsComponent(ref_value="first")]
- )
- )
+ template_values=[parammeter1],
+ bindings=WhatsAppMessageTemplateBindings(
+ body=[WhatsAppMessageTemplateBindingsComponent(ref_value="first")]
+ ),
+ )
raised = False
template_options = TemplateNotificationContent(
- channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959",
- to=[phone_number],
- template=input_template)
+ channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959", to=[phone_number], template=input_template
+ )
- message_response : MessageReceipt = None
+ message_response: MessageReceipt = None
message_client: NotificationMessagesClient = self.create_notification_message_client()
try:
@@ -125,18 +117,17 @@ def test_template_with_parameters_send_message(self):
assert message_response.to is not None
@MessagesPreparers.messages_test_decorator
- @recorded_by_proxy
+ @recorded_by_proxy
def test_image_send_message(self):
phone_number: str = "+14254360097"
input_media_uri: str = "https://aka.ms/acsicon1"
raised = False
template_options = ImageNotificationContent(
- channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959",
- to=[phone_number],
- media_uri=input_media_uri)
+ channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959", to=[phone_number], media_uri=input_media_uri
+ )
- message_response : MessageReceipt = None
+ message_response: MessageReceipt = None
message_client: NotificationMessagesClient = self.create_notification_message_client()
try:
@@ -149,13 +140,12 @@ def test_image_send_message(self):
assert raised is False
assert message_response.message_id is not None
assert message_response.to is not None
-
@MessagesPreparers.messages_test_decorator
- @recorded_by_proxy
+ @recorded_by_proxy
def test_download_media(self):
phone_number: str = "+14254360097"
- input_media_id: str = "8f8c29b2-c2e4-4340-bb28-3009c8a57283"
+ input_media_id: str = "77af35aa-2c17-4c32-8430-53b0559eb920"
raised = False
message_client: NotificationMessagesClient = self.create_notification_message_client()
try:
@@ -165,4 +155,4 @@ def test_download_media(self):
raised = True
raise
assert raised is False
- assert media_stream is not None
\ No newline at end of file
+ assert media_stream is not None
diff --git a/sdk/communication/azure-communication-messages/tests/test_messages_client_async.py b/sdk/communication/azure-communication-messages/tests/test_messages_client_async.py
index 1db009a8ad2b..4b3f13a820c2 100644
--- a/sdk/communication/azure-communication-messages/tests/test_messages_client_async.py
+++ b/sdk/communication/azure-communication-messages/tests/test_messages_client_async.py
@@ -21,26 +21,28 @@
MessageTemplateBindings,
MessageTemplateValue,
WhatsAppMessageTemplateBindings,
- WhatsAppMessageTemplateBindingsComponent
- )
+ WhatsAppMessageTemplateBindingsComponent,
+)
from _shared.utils import get_http_logging_policy
from _messages_test_case_async import AsyncMessagesRecordedTestCase
from azure.communication.messages._shared.utils import parse_connection_str
-
+
+
class TestNotificationMessageClientForTextAsync(AsyncMessagesRecordedTestCase):
- @MessagesPreparersAsync.messages_test_decorator_async
- @recorded_by_proxy_async
+ @MessagesPreparersAsync.messages_test_decorator_async
+ @recorded_by_proxy_async
async def test_text_send_message_async(self):
phone_number: str = "+14254360097"
raised = False
text_options = TextNotificationContent(
channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959",
- to= [phone_number],
- content="Thanks for your feedback Hello.")
+ to=[phone_number],
+ content="Thanks for your feedback Hello.",
+ )
- message_response : MessageReceipt = None
+ message_response: MessageReceipt = None
message_client: NotificationMessagesClient = self.create_notification_message_client()
try:
@@ -54,24 +56,20 @@ async def test_text_send_message_async(self):
assert message_response.message_id is not None
assert message_response.to is not None
-
@MessagesPreparersAsync.messages_test_decorator_async
- @recorded_by_proxy_async
+ @recorded_by_proxy_async
async def test_template_send_message_async(self):
phone_number: str = "+14254360097"
- input_template: MessageTemplate = MessageTemplate(
- name="gathering_invitation",
- language="ca")
+ input_template: MessageTemplate = MessageTemplate(name="gathering_invitation", language="ca")
raised = False
message_client: NotificationMessagesClient = self.create_notification_message_client()
template_options = TemplateNotificationContent(
- channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959",
- to=[phone_number],
- template=input_template)
+ channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959", to=[phone_number], template=input_template
+ )
- message_response : MessageReceipt = None
+ message_response: MessageReceipt = None
try:
async with message_client:
@@ -83,35 +81,29 @@ async def test_template_send_message_async(self):
assert raised is False
assert message_response.message_id is not None
assert message_response.to is not None
-
@MessagesPreparersAsync.messages_test_decorator_async
- @recorded_by_proxy_async
+ @recorded_by_proxy_async
async def test_template_with_parameters_send_message_async(self):
-
+
phone_number: str = "+14254360097"
- parammeter1 = MessageTemplateText (
- name="first",
- text="11-18-2024"
- )
+ parammeter1 = MessageTemplateText(name="first", text="11-18-2024")
input_template: MessageTemplate = MessageTemplate(
name="gathering_invitation",
language="en_US",
- template_values= [parammeter1],
- bindings=WhatsAppMessageTemplateBindings
- (
- body= [ WhatsAppMessageTemplateBindingsComponent(ref_value="first")]
- )
- )
+ template_values=[parammeter1],
+ bindings=WhatsAppMessageTemplateBindings(
+ body=[WhatsAppMessageTemplateBindingsComponent(ref_value="first")]
+ ),
+ )
raised = False
template_options = TemplateNotificationContent(
- channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959",
- to=[phone_number],
- template=input_template)
+ channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959", to=[phone_number], template=input_template
+ )
- message_response : MessageReceipt = None
+ message_response: MessageReceipt = None
message_client: NotificationMessagesClient = self.create_notification_message_client()
try:
@@ -126,18 +118,17 @@ async def test_template_with_parameters_send_message_async(self):
assert message_response.to is not None
@MessagesPreparersAsync.messages_test_decorator_async
- @recorded_by_proxy_async
+ @recorded_by_proxy_async
async def test_image_send_message_async(self):
phone_number: str = "+14254360097"
input_media_uri: str = "https://aka.ms/acsicon1"
raised = False
template_options = ImageNotificationContent(
- channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959",
- to=[phone_number],
- media_uri=input_media_uri)
+ channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959", to=[phone_number], media_uri=input_media_uri
+ )
- message_response : MessageReceipt = None
+ message_response: MessageReceipt = None
message_client: NotificationMessagesClient = self.create_notification_message_client()
try:
@@ -150,13 +141,12 @@ async def test_image_send_message_async(self):
assert raised is False
assert message_response.message_id is not None
assert message_response.to is not None
-
@MessagesPreparersAsync.messages_test_decorator_async
- @recorded_by_proxy_async
+ @recorded_by_proxy_async
async def test_download_media_async(self):
phone_number: str = "+14254360097"
- input_media_id: str = "8f8c29b2-c2e4-4340-bb28-3009c8a57283"
+ input_media_id: str = "77af35aa-2c17-4c32-8430-53b0559eb920"
raised = False
message_client: NotificationMessagesClient = self.create_notification_message_client()
try:
@@ -166,4 +156,4 @@ async def test_download_media_async(self):
raised = True
raise
assert raised is False
- assert media_stream is not None
\ No newline at end of file
+ assert media_stream is not None
diff --git a/sdk/communication/azure-communication-messages/tests/test_messages_template_client.py b/sdk/communication/azure-communication-messages/tests/test_messages_template_client.py
index c4ebb00328e5..3fe9b48523fa 100644
--- a/sdk/communication/azure-communication-messages/tests/test_messages_template_client.py
+++ b/sdk/communication/azure-communication-messages/tests/test_messages_template_client.py
@@ -6,14 +6,12 @@
from devtools_testutils import recorded_by_proxy
from _decorators import MessagesPreparers
-from azure.communication.messages.models import (
- MessageTemplateItem,
- MessageTemplate
- )
+from azure.communication.messages.models import MessageTemplateItem, MessageTemplate
from _shared.utils import get_http_logging_policy
from _messages_test_case import MessagesRecordedTestCase
from azure.communication.messages._shared.utils import parse_connection_str
-
+
+
class TestMessageTemplateClientToGetTemplates(MessagesRecordedTestCase):
@MessagesPreparers.messages_test_decorator
@@ -30,6 +28,6 @@ def test_get_templates(self):
except:
raised = True
raise
-
+
assert raised is False
assert message_template_item_list is not None
diff --git a/sdk/communication/azure-communication-messages/tests/test_messages_template_client_async.py b/sdk/communication/azure-communication-messages/tests/test_messages_template_client_async.py
index 070494a878bd..31726352db10 100644
--- a/sdk/communication/azure-communication-messages/tests/test_messages_template_client_async.py
+++ b/sdk/communication/azure-communication-messages/tests/test_messages_template_client_async.py
@@ -6,18 +6,16 @@
from devtools_testutils.aio import recorded_by_proxy_async
from _decorators_async import MessagesPreparersAsync
-from azure.communication.messages.models import (
- MessageTemplateItem,
- MessageTemplate
- )
+from azure.communication.messages.models import MessageTemplateItem, MessageTemplate
from _shared.utils import get_http_logging_policy
from _messages_test_case_async import AsyncMessagesRecordedTestCase
from azure.communication.messages._shared.utils import parse_connection_str
-
+
+
class TestMessageTemplateClientToGetTemplatesAsync(AsyncMessagesRecordedTestCase):
@MessagesPreparersAsync.messages_test_decorator_async
- @recorded_by_proxy_async
+ @recorded_by_proxy_async
async def test_get_templates_async(self):
channel_id = "b045be8c-45cd-492a-b2a2-47bae7c36959"
raised = False
@@ -30,9 +28,6 @@ async def test_get_templates_async(self):
except:
raised = True
raise
-
+
assert raised is False
assert message_template_item_list is not None
-
-
-
diff --git a/sdk/communication/azure-communication-messages/tests/unittest_helpers.py b/sdk/communication/azure-communication-messages/tests/unittest_helpers.py
index 9d24a0aa86eb..3bc29f4ede4b 100644
--- a/sdk/communication/azure-communication-messages/tests/unittest_helpers.py
+++ b/sdk/communication/azure-communication-messages/tests/unittest_helpers.py
@@ -7,6 +7,7 @@
from unittest import mock
+
def mock_response(status_code=200, headers=None, json_payload=None):
response = mock.Mock(status_code=status_code, headers=headers or {})
if json_payload is not None:
diff --git a/sdk/communication/azure-communication-messages/tsp-location.yaml b/sdk/communication/azure-communication-messages/tsp-location.yaml
index e8d5cb2bd4a1..4292cd594e07 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: 392938969db1bb682734600b9a5c0f0a30a95f58
+commit: abe3209e7c6924a58ab560ebab2349bc8fde6aa7
repo: Azure/azure-rest-api-specs
additionalDirectories: []