diff --git a/eng/tox/allowed_pylint_failures.py b/eng/tox/allowed_pylint_failures.py index c929b50632ab..454d96f3ca4c 100644 --- a/eng/tox/allowed_pylint_failures.py +++ b/eng/tox/allowed_pylint_failures.py @@ -55,6 +55,7 @@ "azure-purview-scanning", "azure-purview-catalog", "azure-purview-account", + "azure-messaging-webpubsubservice", "azure-messaging-nspkg", "azure-agrifood-farming", "azure-eventhub", diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/CHANGELOG.md b/sdk/webpubsub/azure-messaging-webpubsubservice/CHANGELOG.md index 45abf33ffcf2..ef8bdf99210e 100644 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/CHANGELOG.md +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/CHANGELOG.md @@ -2,8 +2,11 @@ ## 1.0.0b2 (Unreleased) +- Add operations to client +- Support AAD +- Support Api Management Proxy ## 1.0.0b1 (2021-04-27) -Initial version +- Initial version diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/MANIFEST.in b/sdk/webpubsub/azure-messaging-webpubsubservice/MANIFEST.in index a3b68055b727..2094336fbe77 100644 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/MANIFEST.in +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/MANIFEST.in @@ -3,4 +3,4 @@ include azure/__init__.py include azure/messaging/__init__.py include LICENSE.txt recursive-include tests *.py -recursive-include examples *.py *.md \ No newline at end of file +recursive-include samples *.py *.md \ No newline at end of file diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/README.md b/sdk/webpubsub/azure-messaging-webpubsubservice/README.md index 9135d4d09e22..bcea06b936c4 100644 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/README.md +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/README.md @@ -43,14 +43,48 @@ python -m pip install azure-messaging-webpubsubservice ### Authenticating the client -In order to interact with the Azure WebPubSub service, you'll need to create an instance of the [WebPubSubServiceClient][webpubsubservice_client_class] class. In order to authenticate against the service, you need to pass in an AzureKeyCredential instance with endpoint and api key. The endpoint and api key can be found on the azure portal. +#### 1. Create with an API Key Credential + +You can get the [API key][api_key] or [Connection string][connection_string] in the [Azure Portal][azure_portal]. +Once you have the value for the API key, you can pass it as a string into an instance of [AzureKeyCredential][azure-key-credential]. +Use the key as the credential parameter to authenticate the client: ```python >>> from azure.messaging.webpubsubservice import WebPubSubServiceClient >>> from azure.core.credentials import AzureKeyCredential ->>> client = WebPubSubServiceClient(endpoint='', credential=AzureKeyCredential('somesecret')) ->>> client -'> + +>>> client = WebPubSubServiceClient(endpoint='', credential=AzureKeyCredential("")) +``` + +Once you have the value for the connection string, you can pass it as a string into the function `from_connection_string` and it will +authenticate the client: +```python +>>> from azure.messaging.webpubsubservice import WebPubSubServiceClient + +>>> client = WebPubSubServiceClient.from_connection_string(connection_string='') +``` + +#### 2. Create with an Azure Active Directory Credential +To use an [Azure Active Directory (AAD) token credential][authenticate_with_token], +provide an instance of the desired credential type obtained from the +[azure-identity][azure_identity_credentials] library. + +To authenticate with AAD, you must first [pip][pip] install [`azure-identity`][azure_identity_pip] and +[enable AAD authentication on your Webpubsub resource][enable_aad] + +After setup, you can choose which type of [credential][azure_identity_credentials] from azure.identity to use. +As an example, [DefaultAzureCredential][default_azure_credential] +can be used to authenticate the client: + +Set the values of the client ID, tenant ID, and client secret of the AAD application as environment variables: +AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET + +Use the returned token credential to authenticate the client: + +```python +>>> from azure.messaging.webpubsubservice import WebPubSubServiceClient +>>> from azure.identity import DefaultAzureCredential +>>> client = WebPubSubServiceClient(endpoint='', credential=DefaultAzureCredential()) ``` ## Examples @@ -59,22 +93,16 @@ In order to interact with the Azure WebPubSub service, you'll need to create an ```python >>> from azure.messaging.webpubsubservice import WebPubSubServiceClient ->>> from azure.core.credentials import AzureKeyCredential ->>> from azure.messaging.webpubsubservice.rest import build_send_to_all_request ->>> client = WebPubSubServiceClient(endpoint='', credential=AzureKeyCredential('somesecret')) ->>> request = build_send_to_all_request('default', json={ 'Hello': 'webpubsub!' }) ->>> request - ->>> response = client.send_request(request) ->>> response - ->>> response.status_code -202 +>>> from azure.identity import DefaultAzureCredential +>>> from azure.core.exceptions import HttpResponseError + +>>> client = WebPubSubServiceClient(endpoint='', credential=DefaultAzureCredential()) >>> with open('file.json', 'r') as f: ->>> request = build_send_to_all_request('ahub', content=f, content_type='application/json') ->>> response = client.send_request(request) ->>> print(response) - + try: + client.send_to_all('ahub', content=f, content_type='application/json') + except HttpResponseError as e: + print('service responds error: {}'.format(e.response.json())) + ``` ## Key concepts @@ -107,10 +135,32 @@ This SDK uses Python standard logging library. You can configure logging print out debugging information to the stdout or anywhere you want. ```python +import sys import logging +from azure.identity import DefaultAzureCredential +>>> from azure.messaging.webpubsubservice import WebPubSubServiceClient + +# Create a logger for the 'azure' SDK +logger = logging.getLogger('azure') +logger.setLevel(logging.DEBUG) -logging.basicConfig(level=logging.DEBUG) -```` +# Configure a console output +handler = logging.StreamHandler(stream=sys.stdout) +logger.addHandler(handler) + +endpoint = "" +credential = DefaultAzureCredential() + +# This client will log detailed information about its HTTP sessions, at DEBUG level +client = WebPubSubServiceClient(endpoint=endpoint, credential=credential, logging_enable=True) +``` + +Similarly, `logging_enable` can enable detailed logging for a single call, +even when it isn't enabled for the client: + +```python +result = client.send_to_all(..., logging_enable=True) +``` Http request and response details are printed to stdout with this logging config. @@ -139,10 +189,19 @@ additional questions or comments. [webpubsubservice_docs]: https://aka.ms/awps/doc [azure_cli]: https://docs.microsoft.com/cli/azure [azure_sub]: https://azure.microsoft.com/free/ -[webpubsubservice_client_class]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/__init__.py [package]: https://pypi.org/project/azure-messaging-webpubsubservice/ [default_cred_ref]: https://aka.ms/azsdk-python-identity-default-cred-ref [cla]: https://cla.microsoft.com [code_of_conduct]: https://opensource.microsoft.com/codeofconduct/ [coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/ [coc_contact]: mailto:opencode@microsoft.com +[authenticate_with_token]: https://docs.microsoft.com/azure/cognitive-services/authentication?tabs=powershell#authenticate-with-an-authentication-token +[azure_identity_credentials]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/identity/azure-identity#credentials +[azure_identity_pip]: https://pypi.org/project/azure-identity/ +[default_azure_credential]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/identity/azure-identity#defaultazurecredential +[pip]: https://pypi.org/project/pip/ +[enable_aad]: https://docs.microsoft.com/azure/azure-web-pubsub/howto-develop-create-instance +[api_key]: https://docs.microsoft.com/azure/azure-web-pubsub/howto-websocket-connect?tabs=browser#authorization +[connection_string]: https://docs.microsoft.com/azure/azure-web-pubsub/howto-websocket-connect?tabs=browser#authorization +[azure_portal]: https://docs.microsoft.com/azure/azure-web-pubsub/howto-develop-create-instance +[azure-key-credential]: https://aka.ms/azsdk-python-core-azurekeycredential diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/__init__.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/__init__.py index 529b1f7e9d7d..46c29b5a072b 100644 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/__init__.py +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/__init__.py @@ -1,232 +1,23 @@ # coding=utf-8 # -------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# +# Licensed under the MIT License. See License.txt in the project root for license information. # Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is -# regenerated. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -__all__ = ["build_authentication_token", "WebPubSubServiceClient"] +from ._web_pub_sub_service_client import WebPubSubServiceClient +from ._version import VERSION -from copy import deepcopy -from datetime import datetime, timedelta -from typing import TYPE_CHECKING +__version__ = VERSION +__all__ = ['WebPubSubServiceClient'] -import jwt -import six +try: + from ._patch import patch_sdk # type: ignore + patch_sdk() -import azure.core.credentials as corecredentials -import azure.core.pipeline as corepipeline -import azure.core.pipeline.policies as corepolicies -import azure.core.pipeline.transport as coretransport - - -# Temporary location for types that eventually graduate to Azure Core -from .core import rest as corerest -from ._version import VERSION as _VERSION -from ._policies import JwtCredentialPolicy -from ._utils import UTC as _UTC - -if TYPE_CHECKING: - from azure.core.pipeline.policies import HTTPPolicy, SansIOHTTPPolicy - from typing import Any, List, cast, Type, TypeVar - - ClientType = TypeVar("ClientType", bound="WebPubSubServiceClient") - - -def _parse_connection_string(connection_string, **kwargs): - for segment in connection_string.split(";"): - if "=" in segment: - key, value = segment.split("=", maxsplit=1) - key = key.lower() - if key not in ("version", ): - kwargs.setdefault(key, value) - elif segment: - raise ValueError( - "Malformed connection string - expected 'key=value', found segment '{}' in '{}'".format( - segment, connection_string - ) - ) - - if "endpoint" not in kwargs: - raise ValueError("connection_string missing 'endpoint' field") - - if "accesskey" not in kwargs: - raise ValueError("connection_string missing 'accesskey' field") - - return kwargs - -def build_authentication_token(endpoint, hub, **kwargs): - """Build an authentication token for the given endpoint, hub using the provided key. - - :keyword endpoint: connetion string or HTTP or HTTPS endpoint for the WebPubSub service instance. - :type endpoint: ~str - :keyword hub: The hub to give access to. - :type hub: ~str - :keyword accesskey: Key to sign the token with. Required if endpoint is not a connection string - :type accesskey: ~str - :keyword ttl: Optional ttl timedelta for the token. Default is 1 hour. - :type ttl: ~datetime.timedelta - :keyword user: Optional user name (subject) for the token. Default is no user. - :type user: ~str - :keyword roles: Roles for the token. - :type roles: typing.List[str]. Default is no roles. - :returns: ~dict containing the web socket endpoint, the token and a url with the generated access token. - :rtype: ~dict - - - Example: - >>> build_authentication_token(endpoint='https://contoso.com/api/webpubsub', hub='theHub', key='123') - { - 'baseUrl': 'wss://contoso.com/api/webpubsub/client/hubs/theHub', - 'token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ...', - 'url': 'wss://contoso.com/api/webpubsub/client/hubs/theHub?access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ...' - } - """ - if 'accesskey' not in kwargs: - kwargs = _parse_connection_string(endpoint, **kwargs) - endpoint = kwargs.pop('endpoint') - - user = kwargs.pop("user", None) - key = kwargs.pop("accesskey") - ttl = kwargs.pop("ttl", timedelta(hours=1)) - roles = kwargs.pop("roles", []) - endpoint = endpoint.lower() - if not endpoint.startswith("http://") and not endpoint.startswith("https://"): - raise ValueError( - "Invalid endpoint: '{}' has unknown scheme - expected 'http://' or 'https://'".format( - endpoint - ) - ) - - # Ensure endpoint has no trailing slash - endpoint = endpoint.rstrip("/") - - # Switch from http(s) to ws(s) scheme - client_endpoint = "ws" + endpoint[4:] - client_url = "{}/client/hubs/{}".format(client_endpoint, hub) - audience = "{}/client/hubs/{}".format(endpoint, hub) - - payload = { - "aud": audience, - "iat": datetime.now(tz=_UTC), - "exp": datetime.now(tz=_UTC) + ttl, - } - if user: - payload["sub"] = user - if roles: - payload["role"] = roles - - token = six.ensure_str(jwt.encode(payload, key, algorithm="HS256")) - return { - "baseUrl": client_url, - "token": token, - "url": "{}?access_token={}".format(client_url, token), - } - - -class WebPubSubServiceClient(object): - def __init__(self, endpoint, credential, **kwargs): - # type: (str, corecredentials.AzureKeyCredential, Any) -> None - """Create a new WebPubSubServiceClient instance - - :param endpoint: Endpoint to connect to. - :type endpoint: ~str - :param credential: Credentials to use to connect to endpoint. - :type credential: ~azure.core.credentials.AzureKeyCredential - :keyword api_version: Api version to use when communicating with the service. - :type api_version: str - :keyword user: User to connect as. Optional. - :type user: ~str - """ - self.endpoint = endpoint.rstrip("/") - transport = kwargs.pop("transport", None) or coretransport.RequestsTransport( - **kwargs - ) - kwargs.setdefault( - "sdk_moniker", "messaging-webpubsubservice/{}".format(_VERSION) - ) - policies = [ - corepolicies.HeadersPolicy(**kwargs), - corepolicies.UserAgentPolicy(**kwargs), - corepolicies.RetryPolicy(**kwargs), - corepolicies.ProxyPolicy(**kwargs), - corepolicies.CustomHookPolicy(**kwargs), - corepolicies.RedirectPolicy(**kwargs), - JwtCredentialPolicy(credential, kwargs.get("user", None)), - corepolicies.NetworkTraceLoggingPolicy(**kwargs), - ] # type: Any - self._pipeline = corepipeline.Pipeline( - transport, - policies, - ) # type: corepipeline.Pipeline - - @classmethod - def from_connection_string(cls, connection_string, **kwargs): - # type: (Type[ClientType], str, Any) -> ClientType - """Create a new WebPubSubServiceClient from a connection string. - - :param connection_string: Connection string - :type connection_string: ~str - :rtype: WebPubSubServiceClient - """ - kwargs = _parse_connection_string(connection_string, **kwargs) - - kwargs["credential"] = corecredentials.AzureKeyCredential( - kwargs.pop("accesskey") - ) - return cls(**kwargs) - - def __repr__(self): - return " endpoint:'{}'".format(self.endpoint) - - def _format_url(self, url): - # type: (str) -> str - assert self.endpoint[-1] != "/", "My endpoint should not have a trailing slash" - return "/".join([self.endpoint, url.lstrip("/")]) - - def send_request(self, http_request, **kwargs): - # type: (corerest.HttpRequest, Any) -> corerest.HttpResponse - """Runs the network request through the client's chained policies. - - We have helper methods to create requests specific to this service in `azure.messaging.webpubsub.rest`. - Use these helper methods to create the request you pass to this method. See our example below: - - >>> from azure.messaging.webpubsub.rest import build_healthapi_get_health_status_request - >>> request = build_healthapi_get_health_status_request(api_version) - - >>> response = client.send_request(request) - - - For more information on this code flow, see https://aka.ms/azsdk/python/llcwiki - - For advanced cases, you can also create your own :class:`~azure.messaging.webpubsub.core.rest.HttpRequest` - and pass it in. - - :param http_request: The network request you want to make. Required. - :type http_request: ~azure.messaging.webpubsub.core.rest.HttpRequest - :keyword bool stream_response: Whether the response payload will be streamed. Defaults to False. - :return: The response of your network call. Does not do error handling on your response. - :rtype: ~azure.messaging.webpubsub.core.rest.HttpResponse - """ - request_copy = deepcopy(http_request) - request_copy.url = self._format_url(request_copy.url) - - # can't do StreamCOntextManager yet. This client doesn't have a pipeline client, - # StreamContextManager requires a pipeline client. WIll look more into it - # if kwargs.pop("stream_response", False): - # return corerest._StreamContextManager( - # client=self._client, - # request=request_copy, - # ) - pipeline_response = self._pipeline.run(request_copy._internal_request, **kwargs) # pylint: disable=protected-access - response = corerest.HttpResponse( - status_code=pipeline_response.http_response.status_code, - request=request_copy, - _internal_response=pipeline_response.http_response, - ) - response.read() - return response + from ._patch import build_authentication_token + from ._patch import WebPubSubServiceClient + __all__ = ['WebPubSubServiceClient', 'build_authentication_token'] +except ImportError: + pass diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_configuration.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_configuration.py new file mode 100644 index 000000000000..e257c83a7382 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_configuration.py @@ -0,0 +1,69 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from typing import TYPE_CHECKING + +from azure.core.configuration import Configuration +from azure.core.pipeline import policies + +from ._version import VERSION + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any, Optional + + from azure.core.credentials import TokenCredential + + +class WebPubSubServiceClientConfiguration(Configuration): + """Configuration for WebPubSubServiceClient. + + Note that all parameters used to create this instance are saved as instance + attributes. + + :param endpoint: HTTP or HTTPS endpoint for the Web PubSub service instance. + :type endpoint: str + :param credential: Credential needed for the client to connect to Azure. + :type credential: ~azure.core.credentials.TokenCredential + """ + + def __init__( + self, + endpoint, # type: str + credential, # type: "TokenCredential" + **kwargs # type: Any + ): + # type: (...) -> None + if endpoint is None: + raise ValueError("Parameter 'endpoint' must not be None.") + if credential is None: + raise ValueError("Parameter 'credential' must not be None.") + super(WebPubSubServiceClientConfiguration, self).__init__(**kwargs) + + self.endpoint = endpoint + self.credential = credential + self.credential_scopes = kwargs.pop('credential_scopes', ['https://webpubsub.azure.com/.default']) + kwargs.setdefault('sdk_moniker', 'messaging-webpubsubservice/{}'.format(VERSION)) + self._configure(**kwargs) + + def _configure( + self, + **kwargs # type: Any + ): + # type: (...) -> 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.retry_policy = kwargs.get('retry_policy') or policies.RetryPolicy(**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.authentication_policy = kwargs.get('authentication_policy') + if self.credential and not self.authentication_policy: + self.authentication_policy = policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_patch.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_patch.py new file mode 100644 index 000000000000..fcd447fee38b --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_patch.py @@ -0,0 +1,327 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the ""Software""), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# -------------------------------------------------------------------------- +import typing +import jwt +import six +from datetime import datetime, timedelta, tzinfo +from typing import TYPE_CHECKING + +from ._version import VERSION +from ._web_pub_sub_service_client import WebPubSubServiceClient as GeneratedWebPubSubServiceClient + +from msrest import Deserializer, Serializer +from azure.core.pipeline import policies +from azure.core import PipelineClient +from azure.core.configuration import Configuration +from azure.core.pipeline.policies import SansIOHTTPPolicy, CustomHookPolicy +from azure.core.credentials import AzureKeyCredential + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Type, TypeVar, Any, Union, Dict + + ClientType = TypeVar("ClientType", bound="WebPubSubServiceClient") + + from azure.core.credentials import TokenCredential + from azure.core.pipeline import PipelineRequest + + +class _UTC_TZ(tzinfo): + """from https://docs.python.org/2/library/datetime.html#tzinfo-objects""" + + ZERO = timedelta(0) + + def utcoffset(self, dt): + return self.__class__.ZERO + + def tzname(self, dt): + return "UTC" + + def dst(self, dt): + return self.__class__.ZERO + + +def _parse_connection_string(connection_string, **kwargs): + # type: (str, Any) -> Dict[Any] + for segment in connection_string.split(";"): + if "=" in segment: + key, value = segment.split("=", maxsplit=1) + key = key.lower() + if key not in ("version",): + kwargs.setdefault(key, value) + elif segment: + raise ValueError( + "Malformed connection string - expected 'key=value', found segment '{}' in '{}'".format( + segment, connection_string + ) + ) + + if "endpoint" not in kwargs: + raise ValueError("connection_string missing 'endpoint' field") + + if "accesskey" not in kwargs: + raise ValueError("connection_string missing 'accesskey' field") + + return kwargs + + +def build_authentication_token(endpoint, hub, **kwargs): + # type: (str, str, Any) -> Dict[Any] + """Build an authentication token for the given endpoint, hub using the provided key. + + :keyword endpoint: connetion string or HTTP or HTTPS endpoint for the WebPubSub service instance. + :type endpoint: str + :keyword hub: The hub to give access to. + :type hub: str + :keyword accesskey: Key to sign the token with. Required if endpoint is not a connection string + :type accesskey: str + :keyword ttl: Optional ttl timedelta for the token. Default is 1 hour. + :type ttl: ~datetime.timedelta + :keyword user: Optional user name (subject) for the token. Default is no user. + :type user: str + :keyword roles: Roles for the token. + :type roles: typing.List[str]. Default is no roles. + :returns: ~dict containing the web socket endpoint, the token and a url with the generated access token. + :rtype: ~dict + + + Example: + >>> build_authentication_token(endpoint='https://contoso.com/api/webpubsub', hub='theHub', key='123') + { + 'baseUrl': 'wss://contoso.com/api/webpubsub/client/hubs/theHub', + 'token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ...', + 'url': 'wss://contoso.com/api/webpubsub/client/hubs/theHub?access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ...' + } + """ + if 'accesskey' not in kwargs: + kwargs = _parse_connection_string(endpoint, **kwargs) + endpoint = kwargs.pop('endpoint') + + user = kwargs.pop("user", None) + key = kwargs.pop("accesskey") + ttl = kwargs.pop("ttl", timedelta(hours=1)) + roles = kwargs.pop("roles", []) + endpoint = endpoint.lower() + if not endpoint.startswith("http://") and not endpoint.startswith("https://"): + raise ValueError( + "Invalid endpoint: '{}' has unknown scheme - expected 'http://' or 'https://'".format( + endpoint + ) + ) + + # Ensure endpoint has no trailing slash + endpoint = endpoint.rstrip("/") + + # Switch from http(s) to ws(s) scheme + client_endpoint = "ws" + endpoint[4:] + client_url = "{}/client/hubs/{}".format(client_endpoint, hub) + audience = "{}/client/hubs/{}".format(endpoint, hub) + + payload = { + "aud": audience, + "iat": datetime.now(tz=_UTC_TZ()), + "exp": datetime.now(tz=_UTC_TZ()) + ttl, + } + if user: + payload["sub"] = user + if roles: + payload["role"] = roles + + token = six.ensure_str(jwt.encode(payload, key, algorithm="HS256")) + return { + "baseUrl": client_url, + "token": token, + "url": "{}?access_token={}".format(client_url, token), + } + + +class JwtCredentialPolicy(SansIOHTTPPolicy): + + NAME_CLAIM_TYPE = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" + + def __init__(self, credential, user=None): + # type: (AzureKeyCredential, typing.Optional[str]) -> None + """Create a new instance of the policy associated with the given credential. + + :param credential: The azure.core.credentials.AzureKeyCredential instance to use + :type credential: ~azure.core.credentials.AzureKeyCredential + :param user: Optional user name associated with the credential. + :type user: str + """ + self._credential = credential + self._user = user + + def on_request(self, request): + # type: (PipelineRequest) -> typing.Union[None, typing.Awaitable[None]] + """Is executed before sending the request from next policy. + + :param request: Request to be modified before sent from next policy. + :type request: ~azure.core.pipeline.PipelineRequest + """ + request.http_request.headers["Authorization"] = "Bearer " + self._encode( + request.http_request.url + ) + return super(JwtCredentialPolicy, self).on_request(request) + + def _encode(self, url): + # type: (AzureKeyCredential) -> str + data = { + "aud": url, + "exp": datetime.now(tz=_UTC_TZ()) + timedelta(seconds=60), + } + if self._user: + data[self.NAME_CLAIM_TYPE] = self._user + + encoded = jwt.encode( + payload=data, + key=self._credential.key, + algorithm="HS256", + ) + return six.ensure_str(encoded) + + +class ApiManagementProxy(CustomHookPolicy): + + def __init__(self, **kwargs): + # type: (typing.Optional[str], typing.Optional[str]) -> None + """Create a new instance of the policy. + + :param endpoint: endpoint to be replaced + :type endpoint: str + :param proxy_endpoint: proxy endpoint + :type proxy_endpoint: str + """ + self._endpoint = kwargs.pop('origin_endpoint', None) + self._reverse_proxy_endpoint = kwargs.pop('reverse_proxy_endpoint', None) + super(ApiManagementProxy, self).__init__(**kwargs) + + def on_request(self, request): + # type: (PipelineRequest) -> None + """Is executed before sending the request from next policy. + + :param request: Request to be modified before sent from next policy. + :type request: ~azure.core.pipeline.PipelineRequest + """ + super(ApiManagementProxy, self).on_request(request) + if self._endpoint and self._reverse_proxy_endpoint: + request.http_request.url = request.http_request.url.replace(self._endpoint, self._reverse_proxy_endpoint) + + +class WebPubSubServiceClientConfiguration(Configuration): + """Configuration for WebPubSubServiceClient. + + Note that all parameters used to create this instance are saved as instance + attributes. + + :param endpoint: HTTP or HTTPS endpoint for the Web PubSub service instance. + :type endpoint: str + :param credential: Credential needed for the client to connect to Azure. + :type credential: Union[~azure.core.credentials.TokenCredential, ~azure.core.credentials.AzureKeyCredential] + """ + + def __init__( + self, + endpoint, # type: str + credential, # type: Union[TokenCredential, AzureKeyCredential] + **kwargs # type: Any + ): + # type: (...) -> None + if endpoint is None: + raise ValueError("Parameter 'endpoint' must not be None.") + if credential is None: + raise ValueError("Parameter 'credential' must not be None.") + super(WebPubSubServiceClientConfiguration, self).__init__(**kwargs) + + self.endpoint = endpoint + self.credential = credential + self.credential_scopes = kwargs.pop('credential_scopes', ['https://webpubsub.azure.com/.default']) + kwargs.setdefault('sdk_moniker', 'messaging-webpubsubservice/{}'.format(VERSION)) + self._configure(**kwargs) + + def _configure( + self, + **kwargs # type: Any + ): + # type: (...) -> 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.retry_policy = kwargs.get('retry_policy') or policies.RetryPolicy(**kwargs) + self.custom_hook_policy = kwargs.get('custom_hook_policy') or ApiManagementProxy(**kwargs) + self.redirect_policy = kwargs.get('redirect_policy') or policies.RedirectPolicy(**kwargs) + self.authentication_policy = kwargs.get('authentication_policy') + if self.credential and not self.authentication_policy: + if isinstance(self.credential, AzureKeyCredential): + self.authentication_policy = JwtCredentialPolicy(self.credential, kwargs.get('user')) + else: + self.authentication_policy = policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) + + +class WebPubSubServiceClient(GeneratedWebPubSubServiceClient): + """WebPubSubServiceClient. + + :param endpoint: HTTP or HTTPS endpoint for the Web PubSub service instance. + :type endpoint: str + :param credential: Credential needed for the client to connect to Azure. + :type credential: ~azure.core.credentials.TokenCredential + """ + + def __init__( + self, + endpoint, # type: str + credential, # type: Union[TokenCredential, AzureKeyCredential] + **kwargs # type: Any + ): + # type: (...) -> None + kwargs['origin_endpoint'] = endpoint + _endpoint = '{Endpoint}' + self._config = WebPubSubServiceClientConfiguration(endpoint, credential, **kwargs) + self._client = PipelineClient(base_url=_endpoint, config=self._config, **kwargs) + + self._serialize = Serializer() + self._deserialize = Deserializer() + self._serialize.client_side_validation = False + + @classmethod + def from_connection_string(cls, connection_string, **kwargs): + # type: (Type[ClientType], str, Any) -> ClientType + """Create a new WebPubSubServiceClient from a connection string. + + :param connection_string: Connection string + :type connection_string: str + :rtype: WebPubSubServiceClient + """ + kwargs = _parse_connection_string(connection_string, **kwargs) + + credential = AzureKeyCredential(kwargs.pop("accesskey")) + return cls(credential=credential, **kwargs) + + +def patch_sdk(): + pass diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_policies.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_policies.py deleted file mode 100644 index 6dc11981689a..000000000000 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_policies.py +++ /dev/null @@ -1,83 +0,0 @@ -# -------------------------------------------------------------------------- -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -# -------------------------------------------------------------------------- - -import datetime -import typing -import jwt -import six - -from azure.core.pipeline.policies import SansIOHTTPPolicy - -from ._utils import UTC - -if typing.TYPE_CHECKING: - from azure.core.credentials import AzureKeyCredential - from azure.core.pipeline import PipelineRequest - - -class JwtCredentialPolicy(SansIOHTTPPolicy): - - NAME_CLAIM_TYPE = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" - - def __init__(self, credential, user=None): - # type: (AzureKeyCredential, typing.Optional[str]) -> None - """Create a new instance of the policy associated with the given credential. - - :param credential: The azure.core.credentials.AzureKeyCredential instance to use - :type credential: ~azure.core.credentials.AzureKeyCredential - :param user: Optional user name associated with the credential. - :type user: str - """ - self._credential = credential - self._user = user - - def on_request(self, request): - # type: (PipelineRequest) -> typing.Union[None, typing.Awaitable[None]] - """Is executed before sending the request from next policy. - - :param request: Request to be modified before sent from next policy. - :type request: ~azure.core.pipeline.PipelineRequest - """ - request.http_request.headers["Authorization"] = "Bearer " + self._encode( - request.http_request.url - ) - return super(JwtCredentialPolicy, self).on_request(request) - - def _encode(self, url): - # type: (AzureKeyCredential) -> str - data = { - "aud": url, - "exp": datetime.datetime.now(tz=UTC) + datetime.timedelta(seconds=60), - } - if self._user: - data[self.NAME_CLAIM_TYPE] = self._user - - encoded = jwt.encode( - payload=data, - key=self._credential.key, - algorithm="HS256", - ) - return six.ensure_str(encoded) diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_utils.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_utils.py deleted file mode 100644 index 042b46dd8848..000000000000 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_utils.py +++ /dev/null @@ -1,45 +0,0 @@ -# -------------------------------------------------------------------------- -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -# -------------------------------------------------------------------------- - -import datetime - - -class _UTC_TZ(datetime.tzinfo): - """from https://docs.python.org/2/library/datetime.html#tzinfo-objects""" - - ZERO = datetime.timedelta(0) - - def utcoffset(self, dt): - return self.__class__.ZERO - - def tzname(self, dt): - return "UTC" - - def dst(self, dt): - return self.__class__.ZERO - - -UTC = _UTC_TZ() diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_version.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_version.py index e1816f2340d7..dfa6ee022f15 100644 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_version.py +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_version.py @@ -1,6 +1,9 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- VERSION = "1.0.0b2" diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_web_pub_sub_service_client.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_web_pub_sub_service_client.py new file mode 100644 index 000000000000..260190e94194 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/_web_pub_sub_service_client.py @@ -0,0 +1,92 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from copy import deepcopy +from typing import TYPE_CHECKING + +from azure.core import PipelineClient +from msrest import Deserializer, Serializer + +from ._configuration import WebPubSubServiceClientConfiguration +from .operations import WebPubSubServiceClientOperationsMixin + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any, Dict, Optional + + from azure.core.credentials import TokenCredential + from azure.core.rest import HttpRequest, HttpResponse + +class WebPubSubServiceClient(WebPubSubServiceClientOperationsMixin): + """WebPubSubServiceClient. + + :param endpoint: HTTP or HTTPS endpoint for the Web PubSub service instance. + :type endpoint: str + :param credential: Credential needed for the client to connect to Azure. + :type credential: ~azure.core.credentials.TokenCredential + """ + + def __init__( + self, + endpoint, # type: str + credential, # type: "TokenCredential" + **kwargs # type: Any + ): + # type: (...) -> None + _endpoint = '{Endpoint}' + self._config = WebPubSubServiceClientConfiguration(endpoint, credential, **kwargs) + self._client = PipelineClient(base_url=_endpoint, config=self._config, **kwargs) + + self._serialize = Serializer() + self._deserialize = Deserializer() + self._serialize.client_side_validation = False + + + def send_request( + self, + request, # type: HttpRequest + **kwargs # type: Any + ): + # type: (...) -> HttpResponse + """Runs the network request through the client's chained policies. + + >>> from azure.core.rest import HttpRequest + >>> request = HttpRequest("GET", "https://www.example.org/") + + >>> response = client.send_request(request) + + + For more information on this code flow, see https://aka.ms/azsdk/python/protocol/quickstart + + :param request: The network request you want to make. Required. + :type request: ~azure.core.rest.HttpRequest + :keyword bool stream: Whether the response payload will be streamed. Defaults to False. + :return: The response of your network call. Does not do error handling on your response. + :rtype: ~azure.core.rest.HttpResponse + """ + + request_copy = deepcopy(request) + path_format_arguments = { + "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) + return self._client.send_request(request_copy, **kwargs) + + def close(self): + # type: () -> None + self._client.close() + + def __enter__(self): + # type: () -> WebPubSubServiceClient + self._client.__enter__() + return self + + def __exit__(self, *exc_details): + # type: (Any) -> None + self._client.__exit__(*exc_details) diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio.py deleted file mode 100644 index 0559416aa7bc..000000000000 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio.py +++ /dev/null @@ -1,110 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -__all__ = ["WebPubSubServiceClient"] - -from typing import TYPE_CHECKING -from copy import deepcopy - -import azure.core.pipeline as corepipeline -import azure.core.pipeline.policies as corepolicies -import azure.core.pipeline.transport as coretransport - -# Temporary location for types that eventually graduate to Azure Core -from .core import rest as corerest - -from ._policies import JwtCredentialPolicy - -if TYPE_CHECKING: - import azure.core.credentials as corecredentials - from azure.core.pipeline.policies import HTTPPolicy, SansIOHTTPPolicy - from typing import Any, List, cast # pylint: disable=ungrouped-imports - - -class WebPubSubServiceClient(object): - def __init__(self, endpoint, credential, **kwargs): - # type: (str, corecredentials.AzureKeyCredential, Any) -> None - """Create a new WebPubSubServiceClient instance - - :param endpoint: Endpoint to connect to. - :type endpoint: ~str - :param credential: Credentials to use to connect to endpoint. - :type credential: ~azure.core.credentials.AzureKeyCredential - :keyword api_version: Api version to use when communicating with the service. - :type api_version: str - :keyword user: User to connect as. Optional. - :type user: ~str - """ - self.endpoint = endpoint.rstrip("/") - transport = kwargs.pop("transport", None) or coretransport.RequestsTransport( - **kwargs - ) - policies = [ - corepolicies.HeadersPolicy(**kwargs), - corepolicies.UserAgentPolicy(**kwargs), - corepolicies.AsyncRetryPolicy(**kwargs), - corepolicies.ProxyPolicy(**kwargs), - corepolicies.CustomHookPolicy(**kwargs), - corepolicies.AsyncRedirectPolicy(**kwargs), - JwtCredentialPolicy(credential, kwargs.get("user", None)), - corepolicies.NetworkTraceLoggingPolicy(**kwargs), - ] # type: Any - self._pipeline = corepipeline.AsyncPipeline( - transport, - policies, - ) # type: corepipeline.AsyncPipeline - - def _format_url(self, url): - # type: (str) -> str - assert self.endpoint[-1] != "/", "My endpoint should not have a trailing slash" - return "/".join([self.endpoint, url.lstrip("/")]) - - async def send_request( - self, http_request: corerest.HttpRequest, **kwargs: "Any" - ) -> corerest.AsyncHttpResponse: - """Runs the network request through the client's chained policies. - - We have helper methods to create requests specific to this service in `azure.messaging.webpubsub.rest`. - Use these helper methods to create the request you pass to this method. See our example below: - - >>> from azure.messaging.webpubsub.rest import build_healthapi_get_health_status_request - >>> request = build_healthapi_get_health_status_request(api_version) - - >>> response = await client.send_request(request) - - - For more information on this code flow, see https://aka.ms/azsdk/python/llcwiki - - For advanced cases, you can also create your own :class:`~azure.messaging.webpubsub.core.rest.HttpRequest` - and pass it in. - - :param http_request: The network request you want to make. Required. - :type http_request: ~azure.messaging.webpubsub.core.rest.HttpRequest - :keyword bool stream_response: Whether the response payload will be streamed. Defaults to False. - :return: The response of your network call. Does not do error handling on your response. - :rtype: ~azure.messaging.webpubsub.core.rest.AsyncHttpResponse - """ - request_copy = deepcopy(http_request) - request_copy.url = self._format_url(request_copy.url) - - # can't do AsyncStreamContextManager yet. This client doesn't have a pipeline client, - # AsyncStreamContextManager requires a pipeline client. WIll look more into it - # if kwargs.pop("stream_response", False): - # return corerest._AsyncStreamContextManager( - # client=self._client, - # request=request_copy, - # ) - pipeline_response = await self._pipeline.run( - request_copy._internal_request, **kwargs # pylint: disable=protected-access - ) - response = corerest.AsyncHttpResponse( - status_code=pipeline_response.http_response.status_code, - request=request_copy, - _internal_response=pipeline_response.http_response, - ) - await response.read() - return response diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/__init__.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/__init__.py new file mode 100644 index 000000000000..0f1f57df7395 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/__init__.py @@ -0,0 +1,19 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from ._web_pub_sub_service_client import WebPubSubServiceClient +__all__ = ['WebPubSubServiceClient'] + +try: + from ._patch import patch_sdk # type: ignore + patch_sdk() + + from ._patch import WebPubSubServiceClient + __all__ = ['WebPubSubServiceClient'] +except ImportError: + pass diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/_configuration.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/_configuration.py new file mode 100644 index 000000000000..f549a3d17b2c --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/_configuration.py @@ -0,0 +1,65 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from typing import Any, Optional, TYPE_CHECKING + +from azure.core.configuration import Configuration +from azure.core.pipeline import policies + +from .._version import VERSION + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from azure.core.credentials_async import AsyncTokenCredential + + +class WebPubSubServiceClientConfiguration(Configuration): + """Configuration for WebPubSubServiceClient. + + Note that all parameters used to create this instance are saved as instance + attributes. + + :param endpoint: HTTP or HTTPS endpoint for the Web PubSub service instance. + :type endpoint: str + :param credential: Credential needed for the client to connect to Azure. + :type credential: ~azure.core.credentials_async.AsyncTokenCredential + """ + + def __init__( + self, + endpoint: str, + credential: "AsyncTokenCredential", + **kwargs: Any + ) -> None: + if endpoint is None: + raise ValueError("Parameter 'endpoint' must not be None.") + if credential is None: + raise ValueError("Parameter 'credential' must not be None.") + super(WebPubSubServiceClientConfiguration, self).__init__(**kwargs) + + self.endpoint = endpoint + self.credential = credential + self.credential_scopes = kwargs.pop('credential_scopes', ['https://webpubsub.azure.com/.default']) + kwargs.setdefault('sdk_moniker', 'messaging-webpubsubservice/{}'.format(VERSION)) + self._configure(**kwargs) + + 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.retry_policy = kwargs.get('retry_policy') or policies.AsyncRetryPolicy(**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.authentication_policy = kwargs.get('authentication_policy') + if self.credential and not self.authentication_policy: + self.authentication_policy = policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/_patch.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/_patch.py new file mode 100644 index 000000000000..822904f98ce1 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/_patch.py @@ -0,0 +1,141 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the ""Software""), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# -------------------------------------------------------------------------- + +from typing import Any, TYPE_CHECKING, Union + + +from azure.core import AsyncPipelineClient +from msrest import Deserializer, Serializer + +from .._version import VERSION +from .._patch import JwtCredentialPolicy, ApiManagementProxy, _parse_connection_string +from ._web_pub_sub_service_client import WebPubSubServiceClient as GeneratedWebPubSubServiceClient + + +from azure.core.configuration import Configuration +from azure.core.pipeline import policies +from azure.core.credentials import AzureKeyCredential + + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Dict, TypeVar, Type + ClientType = TypeVar("ClientType", bound="WebPubSubServiceClient") + + from azure.core.credentials_async import AsyncTokenCredential + + +class WebPubSubServiceClientConfiguration(Configuration): + """Configuration for WebPubSubServiceClient. + + Note that all parameters used to create this instance are saved as instance + attributes. + + :param endpoint: HTTP or HTTPS endpoint for the Web PubSub service instance. + :type endpoint: str + :param credential: Credential needed for the client to connect to Azure. + :type credential: Union[~azure.core.credentials_async.AsyncTokenCredential, ~azure.core.credentials.AzureKeyCredential] + """ + + def __init__( + self, + endpoint: str, + credential: Union["AsyncTokenCredential", "AzureKeyCredential"], + **kwargs: Any + ) -> None: + if endpoint is None: + raise ValueError("Parameter 'endpoint' must not be None.") + if credential is None: + raise ValueError("Parameter 'credential' must not be None.") + super(WebPubSubServiceClientConfiguration, self).__init__(**kwargs) + + self.endpoint = endpoint + self.credential = credential + self.credential_scopes = kwargs.pop('credential_scopes', ['https://webpubsub.azure.com/.default']) + kwargs.setdefault('sdk_moniker', 'messaging-webpubsubservice/{}'.format(VERSION)) + self._configure(**kwargs) + + 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.retry_policy = kwargs.get('retry_policy') or policies.AsyncRetryPolicy(**kwargs) + self.custom_hook_policy = kwargs.get('custom_hook_policy') or ApiManagementProxy(**kwargs) + self.redirect_policy = kwargs.get('redirect_policy') or policies.AsyncRedirectPolicy(**kwargs) + self.authentication_policy = kwargs.get('authentication_policy') + if self.credential and not self.authentication_policy: + if isinstance(self.credential, AzureKeyCredential): + self.authentication_policy = JwtCredentialPolicy(self.credential, kwargs.get('user')) + else: + self.authentication_policy = policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) + + +class WebPubSubServiceClient(GeneratedWebPubSubServiceClient): + """WebPubSubServiceClient. + + :param endpoint: HTTP or HTTPS endpoint for the Web PubSub service instance. + :type endpoint: str + :param credential: Credential needed for the client to connect to Azure. + :type credential: ~azure.core.credentials_async.AsyncTokenCredential + """ + + def __init__( + self, + endpoint: str, + credential: Union["AsyncTokenCredential", "AzureKeyCredential"], + **kwargs: Any + ) -> None: + kwargs['origin_endpoint'] = endpoint + _endpoint = '{Endpoint}' + self._config = WebPubSubServiceClientConfiguration(endpoint, credential, **kwargs) + self._client = AsyncPipelineClient(base_url=_endpoint, config=self._config, **kwargs) + + self._serialize = Serializer() + self._deserialize = Deserializer() + self._serialize.client_side_validation = False + + @classmethod + def from_connection_string(cls, connection_string, **kwargs): + # type: (Type[ClientType], str, Any) -> ClientType + """Create a new WebPubSubServiceClient from a connection string. + :param connection_string: Connection string + :type connection_string: ~str + :rtype: WebPubSubServiceClient + """ + kwargs = _parse_connection_string(connection_string, **kwargs) + + credential = AzureKeyCredential(kwargs.pop("accesskey")) + return cls(credential=credential, **kwargs) + + +def patch_sdk(): + pass diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/_web_pub_sub_service_client.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/_web_pub_sub_service_client.py new file mode 100644 index 000000000000..fe48e209c2a6 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/_web_pub_sub_service_client.py @@ -0,0 +1,87 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from copy import deepcopy +from typing import Any, Awaitable, Optional, TYPE_CHECKING + +from azure.core import AsyncPipelineClient +from azure.core.rest import AsyncHttpResponse, HttpRequest +from msrest import Deserializer, Serializer + +from ._configuration import WebPubSubServiceClientConfiguration +from .operations import WebPubSubServiceClientOperationsMixin + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Dict + + from azure.core.credentials_async import AsyncTokenCredential + +class WebPubSubServiceClient(WebPubSubServiceClientOperationsMixin): + """WebPubSubServiceClient. + + :param endpoint: HTTP or HTTPS endpoint for the Web PubSub service instance. + :type endpoint: str + :param credential: Credential needed for the client to connect to Azure. + :type credential: ~azure.core.credentials_async.AsyncTokenCredential + """ + + def __init__( + self, + endpoint: str, + credential: "AsyncTokenCredential", + **kwargs: Any + ) -> None: + _endpoint = '{Endpoint}' + self._config = WebPubSubServiceClientConfiguration(endpoint, credential, **kwargs) + self._client = AsyncPipelineClient(base_url=_endpoint, config=self._config, **kwargs) + + self._serialize = Serializer() + self._deserialize = Deserializer() + self._serialize.client_side_validation = False + + + def send_request( + self, + request: HttpRequest, + **kwargs: Any + ) -> Awaitable[AsyncHttpResponse]: + """Runs the network request through the client's chained policies. + + >>> from azure.core.rest import HttpRequest + >>> request = HttpRequest("GET", "https://www.example.org/") + + >>> response = await client.send_request(request) + + + For more information on this code flow, see https://aka.ms/azsdk/python/protocol/quickstart + + :param request: The network request you want to make. Required. + :type request: ~azure.core.rest.HttpRequest + :keyword bool stream: Whether the response payload will be streamed. Defaults to False. + :return: The response of your network call. Does not do error handling on your response. + :rtype: ~azure.core.rest.AsyncHttpResponse + """ + + request_copy = deepcopy(request) + path_format_arguments = { + "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) + return self._client.send_request(request_copy, **kwargs) + + async def close(self) -> None: + await self._client.close() + + async def __aenter__(self) -> "WebPubSubServiceClient": + await self._client.__aenter__() + return self + + async def __aexit__(self, *exc_details) -> None: + await self._client.__aexit__(*exc_details) diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/operations/__init__.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/operations/__init__.py new file mode 100644 index 000000000000..af83bc4323b2 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/operations/__init__.py @@ -0,0 +1,13 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from ._operations import WebPubSubServiceClientOperationsMixin + +__all__ = [ + 'WebPubSubServiceClientOperationsMixin', +] diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/operations/_operations.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/operations/_operations.py new file mode 100644 index 000000000000..fa76c744db13 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/aio/operations/_operations.py @@ -0,0 +1,1123 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import functools +from typing import Any, Callable, Dict, Generic, IO, List, Optional, TypeVar, Union +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import AsyncHttpResponse +from azure.core.rest import HttpRequest +from azure.core.tracing.decorator_async import distributed_trace_async + +from ...operations._operations import build_add_connection_to_group_request, build_add_user_to_group_request, build_check_permission_request, build_close_connection_request, build_connection_exists_request, build_generate_client_token_request, build_grant_permission_request, build_group_exists_request, build_remove_connection_from_group_request, build_remove_user_from_all_groups_request, build_remove_user_from_group_request, build_revoke_permission_request, build_send_to_all_request, build_send_to_connection_request, build_send_to_group_request, build_send_to_user_request, build_user_exists_request + +T = TypeVar('T') +ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] + +class WebPubSubServiceClientOperationsMixin: + + @distributed_trace_async + async def generate_client_token( + self, + hub: str, + *, + user_id: Optional[str] = "", + role: Optional[List[str]] = None, + minutes_to_expire: Optional[int] = 60, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> Any: + """Generate token for the client to connect Azure Web PubSub service. + + Generate token for the client to connect Azure Web PubSub service. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :keyword user_id: User Id. + :paramtype user_id: str + :keyword role: Roles that the connection with the generated token will have. + :paramtype role: list[str] + :keyword minutes_to_expire: The expire time of the generated token. + :paramtype minutes_to_expire: int + :keyword api_version: Api Version. + :paramtype api_version: str + :return: JSON object + :rtype: Any + :raises: ~azure.core.exceptions.HttpResponseError + + Example: + .. code-block:: python + + # response body for status code(s): 200 + response.json() == { + "token": "str (optional)" + } + """ + cls = kwargs.pop('cls', None) # type: ClsType[Any] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_generate_client_token_request( + hub=hub, + user_id=user_id, + role=role, + minutes_to_expire=minutes_to_expire, + api_version=api_version, + template_url=self.generate_client_token.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if response.content: + deserialized = response.json() + else: + deserialized = None + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + + generate_client_token.metadata = {'url': '/api/hubs/{hub}/:generateToken'} # type: ignore + + + @distributed_trace_async + async def send_to_all( + self, + hub: str, + message: Union[IO, str], + *, + excluded: Optional[List[str]] = None, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Broadcast content inside request body to all the connected client connections. + + Broadcast content inside request body to all the connected client connections. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param message: The payload body. + :type message: IO or str + :keyword excluded: Excluded connection Ids. + :paramtype excluded: list[str] + :keyword api_version: Api Version. + :paramtype api_version: str + :keyword str content_type: Media type of the body sent to the API. Default value is + "application/json". Allowed values are: "application/json", "application/octet-stream", + "text/plain." + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + content_type = kwargs.pop('content_type', "text/plain") # type: Optional[str] + + json = None + content = None + if content_type.split(";")[0] in ['application/json', 'application/octet-stream']: + content = message + elif content_type.split(";")[0] in ['text/plain']: + json = message + else: + raise ValueError( + "The content_type '{}' is not one of the allowed values: " + "['application/json', 'application/octet-stream', 'text/plain']".format(content_type) + ) + + request = build_send_to_all_request( + hub=hub, + content_type=content_type, + excluded=excluded, + api_version=api_version, + json=json, + content=content, + template_url=self.send_to_all.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + send_to_all.metadata = {'url': '/api/hubs/{hub}/:send'} # type: ignore + + + @distributed_trace_async + async def connection_exists( + self, + hub: str, + connection_id: str, + *, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Check if the connection with the given connectionId exists. + + Check if the connection with the given connectionId exists. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param connection_id: The connection Id. + :type connection_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_connection_exists_request( + hub=hub, + connection_id=connection_id, + api_version=api_version, + template_url=self.connection_exists.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + connection_exists.metadata = {'url': '/api/hubs/{hub}/connections/{connectionId}'} # type: ignore + + + @distributed_trace_async + async def close_connection( + self, + hub: str, + connection_id: str, + *, + reason: Optional[str] = None, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Close the client connection. + + Close the client connection. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param connection_id: Target connection Id. + :type connection_id: str + :keyword reason: The reason closing the client connection. + :paramtype reason: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_close_connection_request( + hub=hub, + connection_id=connection_id, + reason=reason, + api_version=api_version, + template_url=self.close_connection.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + close_connection.metadata = {'url': '/api/hubs/{hub}/connections/{connectionId}'} # type: ignore + + + @distributed_trace_async + async def send_to_connection( + self, + hub: str, + connection_id: str, + message: Union[IO, str], + *, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Send content inside request body to the specific connection. + + Send content inside request body to the specific connection. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param connection_id: The connection Id. + :type connection_id: str + :param message: The payload body. + :type message: IO or str + :keyword api_version: Api Version. + :paramtype api_version: str + :keyword str content_type: Media type of the body sent to the API. Default value is + "application/json". Allowed values are: "application/json", "application/octet-stream", + "text/plain." + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + content_type = kwargs.pop('content_type', "text/plain") # type: Optional[str] + + json = None + content = None + if content_type.split(";")[0] in ['application/json', 'application/octet-stream']: + content = message + elif content_type.split(";")[0] in ['text/plain']: + json = message + else: + raise ValueError( + "The content_type '{}' is not one of the allowed values: " + "['application/json', 'application/octet-stream', 'text/plain']".format(content_type) + ) + + request = build_send_to_connection_request( + hub=hub, + connection_id=connection_id, + content_type=content_type, + api_version=api_version, + json=json, + content=content, + template_url=self.send_to_connection.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + send_to_connection.metadata = {'url': '/api/hubs/{hub}/connections/{connectionId}/:send'} # type: ignore + + + @distributed_trace_async + async def group_exists( + self, + hub: str, + group: str, + *, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Check if there are any client connections inside the given group. + + Check if there are any client connections inside the given group. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param group: Target group name, which length should be greater than 0 and less than 1025. + :type group: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_group_exists_request( + hub=hub, + group=group, + api_version=api_version, + template_url=self.group_exists.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + group_exists.metadata = {'url': '/api/hubs/{hub}/groups/{group}'} # type: ignore + + + @distributed_trace_async + async def send_to_group( + self, + hub: str, + group: str, + message: Union[IO, str], + *, + excluded: Optional[List[str]] = None, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Send content inside request body to a group of connections. + + Send content inside request body to a group of connections. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param group: Target group name, which length should be greater than 0 and less than 1025. + :type group: str + :param message: The payload body. + :type message: IO or str + :keyword excluded: Excluded connection Ids. + :paramtype excluded: list[str] + :keyword api_version: Api Version. + :paramtype api_version: str + :keyword str content_type: Media type of the body sent to the API. Default value is + "application/json". Allowed values are: "application/json", "application/octet-stream", + "text/plain." + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + content_type = kwargs.pop('content_type', "text/plain") # type: Optional[str] + + json = None + content = None + if content_type.split(";")[0] in ['application/json', 'application/octet-stream']: + content = message + elif content_type.split(";")[0] in ['text/plain']: + json = message + else: + raise ValueError( + "The content_type '{}' is not one of the allowed values: " + "['application/json', 'application/octet-stream', 'text/plain']".format(content_type) + ) + + request = build_send_to_group_request( + hub=hub, + group=group, + content_type=content_type, + excluded=excluded, + api_version=api_version, + json=json, + content=content, + template_url=self.send_to_group.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + send_to_group.metadata = {'url': '/api/hubs/{hub}/groups/{group}/:send'} # type: ignore + + + @distributed_trace_async + async def add_connection_to_group( + self, + hub: str, + group: str, + connection_id: str, + *, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Add a connection to the target group. + + Add a connection to the target group. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param group: Target group name, which length should be greater than 0 and less than 1025. + :type group: str + :param connection_id: Target connection Id. + :type connection_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_add_connection_to_group_request( + hub=hub, + group=group, + connection_id=connection_id, + api_version=api_version, + template_url=self.add_connection_to_group.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + add_connection_to_group.metadata = {'url': '/api/hubs/{hub}/groups/{group}/connections/{connectionId}'} # type: ignore + + + @distributed_trace_async + async def remove_connection_from_group( + self, + hub: str, + group: str, + connection_id: str, + *, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Remove a connection from the target group. + + Remove a connection from the target group. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param group: Target group name, which length should be greater than 0 and less than 1025. + :type group: str + :param connection_id: Target connection Id. + :type connection_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_remove_connection_from_group_request( + hub=hub, + group=group, + connection_id=connection_id, + api_version=api_version, + template_url=self.remove_connection_from_group.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + remove_connection_from_group.metadata = {'url': '/api/hubs/{hub}/groups/{group}/connections/{connectionId}'} # type: ignore + + + @distributed_trace_async + async def user_exists( + self, + hub: str, + user_id: str, + *, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Check if there are any client connections connected for the given user. + + Check if there are any client connections connected for the given user. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param user_id: Target user Id. + :type user_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_user_exists_request( + hub=hub, + user_id=user_id, + api_version=api_version, + template_url=self.user_exists.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + user_exists.metadata = {'url': '/api/hubs/{hub}/users/{userId}'} # type: ignore + + + @distributed_trace_async + async def send_to_user( + self, + hub: str, + user_id: str, + message: Union[IO, str], + *, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Send content inside request body to the specific user. + + Send content inside request body to the specific user. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param user_id: The user Id. + :type user_id: str + :param message: The payload body. + :type message: IO or str + :keyword api_version: Api Version. + :paramtype api_version: str + :keyword str content_type: Media type of the body sent to the API. Default value is + "application/json". Allowed values are: "application/json", "application/octet-stream", + "text/plain." + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + content_type = kwargs.pop('content_type', "text/plain") # type: Optional[str] + + json = None + content = None + if content_type.split(";")[0] in ['application/json', 'application/octet-stream']: + content = message + elif content_type.split(";")[0] in ['text/plain']: + json = message + else: + raise ValueError( + "The content_type '{}' is not one of the allowed values: " + "['application/json', 'application/octet-stream', 'text/plain']".format(content_type) + ) + + request = build_send_to_user_request( + hub=hub, + user_id=user_id, + content_type=content_type, + api_version=api_version, + json=json, + content=content, + template_url=self.send_to_user.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + send_to_user.metadata = {'url': '/api/hubs/{hub}/users/{userId}/:send'} # type: ignore + + + @distributed_trace_async + async def add_user_to_group( + self, + hub: str, + group: str, + user_id: str, + *, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Add a user to the target group. + + Add a user to the target group. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param group: Target group name, which length should be greater than 0 and less than 1025. + :type group: str + :param user_id: Target user Id. + :type user_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_add_user_to_group_request( + hub=hub, + group=group, + user_id=user_id, + api_version=api_version, + template_url=self.add_user_to_group.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + add_user_to_group.metadata = {'url': '/api/hubs/{hub}/users/{userId}/groups/{group}'} # type: ignore + + + @distributed_trace_async + async def remove_user_from_group( + self, + hub: str, + group: str, + user_id: str, + *, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Remove a user from the target group. + + Remove a user from the target group. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param group: Target group name, which length should be greater than 0 and less than 1025. + :type group: str + :param user_id: Target user Id. + :type user_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_remove_user_from_group_request( + hub=hub, + group=group, + user_id=user_id, + api_version=api_version, + template_url=self.remove_user_from_group.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + remove_user_from_group.metadata = {'url': '/api/hubs/{hub}/users/{userId}/groups/{group}'} # type: ignore + + + @distributed_trace_async + async def remove_user_from_all_groups( + self, + hub: str, + user_id: str, + *, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Remove a user from all groups. + + Remove a user from all groups. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param user_id: Target user Id. + :type user_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_remove_user_from_all_groups_request( + hub=hub, + user_id=user_id, + api_version=api_version, + template_url=self.remove_user_from_all_groups.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + remove_user_from_all_groups.metadata = {'url': '/api/hubs/{hub}/users/{userId}/groups'} # type: ignore + + + @distributed_trace_async + async def grant_permission( + self, + hub: str, + permission: str, + connection_id: str, + *, + target_name: Optional[str] = None, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Grant permission to the connection. + + Grant permission to the connection. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param permission: The permission: current supported actions are joinLeaveGroup and + sendToGroup. Possible values are: "sendToGroup" or "joinLeaveGroup". + :type permission: str + :param connection_id: Target connection Id. + :type connection_id: str + :keyword target_name: The meaning of the target depends on the specific permission. For + joinLeaveGroup and sendToGroup, targetName is a required parameter standing for the group name. + :paramtype target_name: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_grant_permission_request( + hub=hub, + permission=permission, + connection_id=connection_id, + target_name=target_name, + api_version=api_version, + template_url=self.grant_permission.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + grant_permission.metadata = {'url': '/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}'} # type: ignore + + + @distributed_trace_async + async def revoke_permission( + self, + hub: str, + permission: str, + connection_id: str, + *, + target_name: Optional[str] = None, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Revoke permission for the connection. + + Revoke permission for the connection. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param permission: The permission: current supported actions are joinLeaveGroup and + sendToGroup. Possible values are: "sendToGroup" or "joinLeaveGroup". + :type permission: str + :param connection_id: Target connection Id. + :type connection_id: str + :keyword target_name: The meaning of the target depends on the specific permission. For + joinLeaveGroup and sendToGroup, targetName is a required parameter standing for the group name. + :paramtype target_name: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_revoke_permission_request( + hub=hub, + permission=permission, + connection_id=connection_id, + target_name=target_name, + api_version=api_version, + template_url=self.revoke_permission.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + revoke_permission.metadata = {'url': '/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}'} # type: ignore + + + @distributed_trace_async + async def check_permission( + self, + hub: str, + permission: str, + connection_id: str, + *, + target_name: Optional[str] = None, + api_version: Optional[str] = "2021-08-01-preview", + **kwargs: Any + ) -> None: + """Check if a connection has permission to the specified action. + + Check if a connection has permission to the specified action. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param permission: The permission: current supported actions are joinLeaveGroup and + sendToGroup. Possible values are: "sendToGroup" or "joinLeaveGroup". + :type permission: str + :param connection_id: Target connection Id. + :type connection_id: str + :keyword target_name: The meaning of the target depends on the specific permission. For + joinLeaveGroup and sendToGroup, targetName is a required parameter standing for the group name. + :paramtype target_name: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + + request = build_check_permission_request( + hub=hub, + permission=permission, + connection_id=connection_id, + target_name=target_name, + api_version=api_version, + template_url=self.check_permission.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = await self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + check_permission.metadata = {'url': '/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}'} # type: ignore + diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/core/__init__.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/core/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/core/rest/__init__.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/core/rest/__init__.py deleted file mode 100644 index a70aae7c472a..000000000000 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/core/rest/__init__.py +++ /dev/null @@ -1,65 +0,0 @@ -# -------------------------------------------------------------------------- -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -# -------------------------------------------------------------------------- -try: - from ._rest_py3 import ( - HttpRequest, - HttpResponse, - AsyncHttpResponse, - _StreamContextManager, - _AsyncStreamContextManager, - StreamConsumedError, - ResponseNotReadError, - ResponseClosedError, - ) - - __all__ = [ - "HttpRequest", - "HttpResponse", - "AsyncHttpResponse", - "_StreamContextManager", - "_AsyncStreamContextManager", - "StreamConsumedError", - "ResponseNotReadError", - "ResponseClosedError", - ] -except (SyntaxError, ImportError): - from ._rest import ( - HttpRequest, - HttpResponse, - _StreamContextManager, - StreamConsumedError, - ResponseNotReadError, - ResponseClosedError, - ) - - __all__ = [ - "HttpRequest", - "HttpResponse", - "_StreamContextManager", - "StreamConsumedError", - "ResponseNotReadError", - "ResponseClosedError", - ] diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/core/rest/_rest.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/core/rest/_rest.py deleted file mode 100644 index cee1c039cbda..000000000000 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/core/rest/_rest.py +++ /dev/null @@ -1,625 +0,0 @@ -# -------------------------------------------------------------------------- -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -# -------------------------------------------------------------------------- - -# pylint currently complains about typing.Union not being subscriptable -# pylint: disable=unsubscriptable-object - -import codecs -import json -from enum import Enum -import xml.etree.ElementTree as ET -from typing import TYPE_CHECKING, Iterable - -import cgi -import six - -from azure.core.exceptions import HttpResponseError -from azure.core.pipeline.transport import ( - HttpRequest as _PipelineTransportHttpRequest, -) - - -if TYPE_CHECKING: - from typing import ( # pylint: disable=ungrouped-imports - Any, - Optional, - Union, - Mapping, - Sequence, - Tuple, - Iterator, - ) - - ByteStream = Iterable[bytes] - - HeadersType = Union[Mapping[str, str], Sequence[Tuple[str, str]]] - ContentType = Union[str, bytes, ByteStream] - from azure.core.pipeline.transport._base import ( - _HttpResponseBase as _PipelineTransportHttpResponseBase, - ) - from azure.core._pipeline_client import PipelineClient as _PipelineClient - - -class HttpVerbs(str, Enum): - GET = "GET" - PUT = "PUT" - POST = "POST" - HEAD = "HEAD" - PATCH = "PATCH" - DELETE = "DELETE" - MERGE = "MERGE" - - -########################### UTILS SECTION ################################# - - -def _is_stream_or_str_bytes(content): - return isinstance(content, (str, bytes)) or any( - hasattr(content, attr) for attr in ["read", "__iter__", "__aiter__"] - ) - - -def _lookup_encoding(encoding): - # type: (str) -> bool - # including check for whether encoding is known taken from httpx - try: - codecs.lookup(encoding) - return True - except LookupError: - return False - - -def _set_content_length_header(header_name, header_value, internal_request): - # type: (str, str, _PipelineTransportHttpRequest) -> None - valid_methods = ["put", "post", "patch"] - content_length_headers = ["Content-Length", "Transfer-Encoding"] - if internal_request.method.lower() in valid_methods and not any( - [c for c in content_length_headers if c in internal_request.headers] - ): - internal_request.headers[header_name] = header_value - - -def _set_content_type_header(header_value, internal_request): - # type: (str, _PipelineTransportHttpRequest) -> None - if not internal_request.headers.get("Content-Type"): - internal_request.headers["Content-Type"] = header_value - - -def _set_content_body(content, internal_request): - # type: (ContentType, _PipelineTransportHttpRequest) -> None - headers = internal_request.headers - content_type = headers.get("Content-Type") - if _is_stream_or_str_bytes(content): - # stream will be bytes / str, or iterator of bytes / str - internal_request.set_streamed_data_body(content) - if isinstance(content, (str, bytes)) and content: - _set_content_length_header( - "Content-Length", str(len(internal_request.data)), internal_request - ) - if isinstance(content, six.string_types): - _set_content_type_header("text/plain", internal_request) - else: - _set_content_type_header("application/octet-stream", internal_request) - elif isinstance( # pylint: disable=isinstance-second-argument-not-valid-type - content, Iterable - ): - # _set_content_length_header("Transfer-Encoding", "chunked", internal_request) - _set_content_type_header("application/octet-stream", internal_request) - elif isinstance(content, ET.Element): - # XML body - internal_request.set_xml_body(content) - _set_content_type_header("application/xml", internal_request) - _set_content_length_header( - "Content-Length", str(len(internal_request.data)), internal_request - ) - elif content_type and content_type.startswith("text/"): - # Text body - internal_request.set_text_body(content) - _set_content_length_header( - "Content-Length", str(len(internal_request.data)), internal_request - ) - else: - # Other body - internal_request.data = content - internal_request.headers = headers - - -def _set_body(content, data, files, json_body, internal_request): - # type: (ContentType, dict, Any, Any, _PipelineTransportHttpRequest) -> None - if data is not None and not isinstance(data, dict): - content = data - data = None - if content is not None: - _set_content_body(content, internal_request) - elif json_body is not None: - internal_request.set_json_body(json_body) - _set_content_type_header("application/json", internal_request) - elif files is not None: - internal_request.set_formdata_body(files) - # if you don't supply your content type, we'll create a boundary for you with multipart/form-data - # boundary = binascii.hexlify(os.urandom(16)).decode("ascii") # got logic from httpx, thanks httpx! - # _set_content_type_header("multipart/form-data; boundary={}".format(boundary), internal_request) - elif data: - _set_content_type_header("application/x-www-form-urlencoded", internal_request) - internal_request.set_formdata_body(data) - # need to set twice because Content-Type is being popped in set_formdata_body - # don't want to risk changing pipeline.transport, so doing twice here - _set_content_type_header("application/x-www-form-urlencoded", internal_request) - - -def _parse_lines_from_text(text): - # largely taken from httpx's LineDecoder code - lines = [] - last_chunk_of_text = "" - while text: - text_length = len(text) - for idx in range(text_length): - curr_char = text[idx] - next_char = None if idx == len(text) - 1 else text[idx + 1] - if curr_char == "\n": - lines.append(text[: idx + 1]) - text = text[idx + 1 :] - break - if curr_char == "\r" and next_char == "\n": - # if it ends with \r\n, we only do \n - lines.append(text[:idx] + "\n") - text = text[idx + 2 :] - break - if curr_char == "\r" and next_char is not None: - # if it's \r then a normal character, we switch \r to \n - lines.append(text[:idx] + "\n") - text = text[idx + 1 :] - break - if next_char is None: - text = "" - last_chunk_of_text += text - break - if last_chunk_of_text.endswith("\r"): - # if ends with \r, we switch \r to \n - lines.append(last_chunk_of_text[:-1] + "\n") - elif last_chunk_of_text: - lines.append(last_chunk_of_text) - return lines - - -################################## CLASSES ###################################### -class _StreamContextManager(object): - def __init__(self, client, request, **kwargs): - # type: (_PipelineClient, HttpRequest, Any) -> None - self.client = client - self.request = request - self.kwargs = kwargs - - def __enter__(self): - # type: (...) -> HttpResponse - """Actually make the call only when we enter. For sync stream_response calls""" - pipeline_transport_response = self.client._pipeline.run( - self.request._internal_request, stream=True, **self.kwargs - ).http_response - self.response = HttpResponse( # pylint: disable=attribute-defined-outside-init - request=self.request, _internal_response=pipeline_transport_response - ) - return self.response - - def __exit__(self, *args): - """Close our stream connection. For sync calls""" - self.response.__exit__(*args) - - def close(self): - self.response.close() - - -class HttpRequest(object): - """Represents an HTTP request. - - :param method: HTTP method (GET, HEAD, etc.) - :type method: str or ~azure.core.protocol.HttpVerbs - :param str url: The url for your request - :keyword params: Query parameters to be mapped into your URL. Your input - should be a mapping or sequence of query name to query value(s). - :paramtype params: mapping or sequence - :keyword headers: HTTP headers you want in your request. Your input should - be a mapping or sequence of header name to header value. - :paramtype headers: mapping or sequence - :keyword dict data: Form data you want in your request body. Use for form-encoded data, i.e. - HTML forms. - :keyword any json: A JSON serializable object. We handle JSON-serialization for your - object, so use this for more complicated data structures than `data`. - :keyword files: Files you want to in your request body. Use for uploading files with - multipart encoding. Your input should be a mapping or sequence of file name to file content. - Use the `data` kwarg in addition if you want to include non-file data files as part of your request. - :paramtype files: mapping or sequence - :keyword content: Content you want in your request body. Think of it as the kwarg you should input - if your data doesn't fit into `json`, `data`, or `files`. Accepts a bytes type, or a generator - that yields bytes. - :paramtype content: str or bytes or iterable[bytes] or asynciterable[bytes] - :ivar str url: The URL this request is against. - :ivar str method: The method type of this request. - :ivar headers: The HTTP headers you passed in to your request - :vartype headers: mapping or sequence - :ivar bytes content: The content passed in for the request - """ - - def __init__(self, method, url, **kwargs): - # type: (str, str, Any) -> None - - data = kwargs.pop("data", None) - content = kwargs.pop("content", None) - json_body = kwargs.pop("json", None) - files = kwargs.pop("files", None) - - self._internal_request = kwargs.pop( - "_internal_request", - _PipelineTransportHttpRequest( - method=method, - url=url, - headers=kwargs.pop("headers", None), - ), - ) - params = kwargs.pop("params", None) - - if params: - self._internal_request.format_parameters(params) - - _set_body( - content=content, - data=data, - files=files, - json_body=json_body, - internal_request=self._internal_request, - ) - - if kwargs: - raise TypeError( - "You have passed in kwargs '{}' that are not valid kwargs.".format( - "', '".join(list(kwargs.keys())) - ) - ) - - def _set_content_length_header(self): - method_check = self._internal_request.method.lower() in ["put", "post", "patch"] - content_length_unset = "Content-Length" not in self._internal_request.headers - if method_check and content_length_unset: - self._internal_request.headers["Content-Length"] = str( - len(self._internal_request.data) - ) - - @property - def url(self): - # type: (...) -> str - return self._internal_request.url - - @url.setter - def url(self, val): - # type: (str) -> None - self._internal_request.url = val - - @property - def method(self): - # type: (...) -> str - return self._internal_request.method - - @property - def headers(self): - # type: (...) -> HeadersType - return self._internal_request.headers - - @property - def content(self): - # type: (...) -> Any - """Gets the request content.""" - return self._internal_request.data or self._internal_request.files - - def __repr__(self): - return self._internal_request.__repr__() - - def __deepcopy__(self, memo=None): - return HttpRequest( - self.method, - self.url, - _internal_request=self._internal_request.__deepcopy__(memo), - ) - - -class _HttpResponseBase(object): - """Base class for HttpResponse and AsyncHttpResponse. - - :keyword request: The request that resulted in this response. - :paramtype request: ~azure.core.rest.HttpRequest - :ivar int status_code: The status code of this response - :ivar headers: The response headers - :vartype headers: dict[str, any] - :ivar str reason: The reason phrase for this response - :ivar bytes content: The response content in bytes - :ivar str url: The URL that resulted in this response - :ivar str encoding: The response encoding. Is settable, by default - is the response Content-Type header - :ivar str text: The response body as a string. - :ivar request: The request that resulted in this response. - :vartype request: ~azure.core.rest.HttpRequest - :ivar str content_type: The content type of the response - :ivar bool is_error: Whether this response is an error. - """ - - def __init__(self, **kwargs): - # type: (Any) -> None - self._internal_response = kwargs.pop( - "_internal_response" - ) # type: _PipelineTransportHttpResponseBase - self._request = kwargs.pop("request") - self.is_closed = False - self.is_stream_consumed = False - self._num_bytes_downloaded = 0 - - @property - def status_code(self): - # type: (...) -> int - """Returns the status code of the response""" - return self._internal_response.status_code - - @status_code.setter - def status_code(self, val): - # type: (int) -> None - """Set the status code of the response""" - self._internal_response.status_code = val - - @property - def headers(self): - # type: (...) -> HeadersType - """Returns the response headers""" - return self._internal_response.headers - - @property - def reason(self): - # type: (...) -> str - """Returns the reason phrase for the response""" - return self._internal_response.reason - - @property - def content(self): - # type: (...) -> bytes - """Returns the response content in bytes""" - raise NotImplementedError() - - @property - def url(self): - # type: (...) -> str - """Returns the URL that resulted in this response""" - return self._internal_response.request.url - - @property - def encoding(self): - # type: (...) -> Optional[str] - """Returns the response encoding. By default, is specified - by the response Content-Type header. - """ - - try: - return self._encoding - except AttributeError: - return self._get_charset_encoding() - - def _get_charset_encoding(self): - content_type = self.headers.get("Content-Type") - - if not content_type: - return None - _, params = cgi.parse_header(content_type) - encoding = params.get("charset") # -> utf-8 - if encoding is None or not _lookup_encoding(encoding): - return None - return encoding - - @encoding.setter - def encoding(self, value): - # type: (str) -> None - """Sets the response encoding""" - self._encoding = value - - @property - def text(self): - # type: (...) -> str - """Returns the response body as a string""" - _ = ( - self.content - ) # access content to make sure we trigger if response not fully read in - return self._internal_response.text(encoding=self.encoding) - - @property - def request(self): - # type: (...) -> HttpRequest - if self._request: - return self._request - raise RuntimeError( - "You are trying to access the 'request', but there is no request associated with this HttpResponse" - ) - - @request.setter - def request(self, val): - # type: (HttpRequest) -> None - self._request = val - - @property - def content_type(self): - # type: (...) -> Optional[str] - """Content Type of the response""" - return self._internal_response.content_type or self.headers.get("Content-Type") - - @property - def num_bytes_downloaded(self): - # type: (...) -> int - """See how many bytes of your stream response have been downloaded""" - return self._num_bytes_downloaded - - @property - def is_error(self): - # type: (...) -> bool - """See whether your HttpResponse is an error. - - Use .raise_for_status() if you want to raise if this response is an error. - """ - return self.status_code < 400 - - def json(self): - # type: (...) -> Any - """Returns the whole body as a json object. - - :return: The JSON deserialized response body - :rtype: any - :raises json.decoder.JSONDecodeError or ValueError (in python 2.7) if object is not JSON decodable: - """ - return json.loads(self.text) - - def raise_for_status(self): - # type: (...) -> None - """Raises an HttpResponseError if the response has an error status code. - - If response is good, does nothing. - """ - if self.status_code >= 400: - raise HttpResponseError(response=self) - - def __repr__(self): - # type: (...) -> str - content_type_str = ( - ", Content-Type: {}".format(self.content_type) if self.content_type else "" - ) - return "<{}: {} {}{}>".format( - type(self).__name__, self.status_code, self.reason, content_type_str - ) - - def _validate_streaming_access(self): - # type: (...) -> None - if self.is_closed: - raise ResponseClosedError() - if self.is_stream_consumed: - raise StreamConsumedError() - - -class HttpResponse(_HttpResponseBase): - @property - def content(self): - # type: (...) -> bytes - try: - return self._content - except AttributeError: - raise ResponseNotReadError() - - def close(self): - # type: (...) -> None - self.is_closed = True - self._internal_response.internal_response.close() - - def __exit__(self, *args): - # type: (...) -> None - self._internal_response.internal_response.__exit__(*args) - - def read(self): - # type: (...) -> bytes - """ - Read the response's bytes. - - """ - try: - return self._content - except AttributeError: - self._validate_streaming_access() - self._content = ( # pylint: disable=attribute-defined-outside-init - self._internal_response.body() or b"".join(self.iter_raw()) - ) - self._close_stream() - return self._content - - def iter_bytes(self, chunk_size=None): - # type: (int) -> Iterator[bytes] - """Iterate over the bytes in the response stream""" - try: - chunk_size = len(self._content) if chunk_size is None else chunk_size - for i in range(0, len(self._content), chunk_size): - yield self._content[i : i + chunk_size] - - except AttributeError: - for raw_bytes in self.iter_raw(chunk_size=chunk_size): - yield raw_bytes - - def iter_text(self, chunk_size=None): - # type: (int) -> Iterator[str] - """Iterate over the response text""" - for byte in self.iter_bytes(chunk_size): - text = byte.decode(self.encoding or "utf-8") - yield text - - def iter_lines(self, chunk_size=None): - # type: (int) -> Iterator[str] - for text in self.iter_text(chunk_size): - lines = _parse_lines_from_text(text) - for line in lines: - yield line - - def _close_stream(self): - # type: (...) -> None - self.is_stream_consumed = True - self.close() - - def iter_raw(self, **_): - # type: (int) -> Iterator[bytes] - """Iterate over the raw response bytes""" - self._validate_streaming_access() - stream_download = self._internal_response.stream_download(None) - for raw_bytes in stream_download: - self._num_bytes_downloaded += len(raw_bytes) - yield raw_bytes - - self._close_stream() - - -########################### ERRORS SECTION ################################# - - -class StreamConsumedError(Exception): - def __init__(self): - message = ( - "You are attempting to read or stream content that has already been streamed. " - "You have likely already consumed this stream, so it can not be accessed anymore." - ) - super(StreamConsumedError, self).__init__(message) - - -class ResponseClosedError(Exception): - def __init__(self): - message = ( - "You can not try to read or stream this response's content, since the " - "response has been closed." - ) - super(ResponseClosedError, self).__init__(message) - - -class ResponseNotReadError(Exception): - def __init__(self): - message = ( - "You have not read in the response's bytes yet. Call response.read() first." - ) - super(ResponseNotReadError, self).__init__(message) diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/core/rest/_rest_py3.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/core/rest/_rest_py3.py deleted file mode 100644 index ed2908d69484..000000000000 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/core/rest/_rest_py3.py +++ /dev/null @@ -1,739 +0,0 @@ -# -------------------------------------------------------------------------- -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -# -------------------------------------------------------------------------- - -# pylint currently complains about typing.Union not being subscriptable -# pylint: disable=unsubscriptable-object - - -import asyncio -import codecs -import json -from enum import Enum -import xml.etree.ElementTree as ET -from typing import ( - Any, - AsyncIterable, - IO, - Iterable, - Iterator, - Optional, - Union, - Mapping, - Sequence, - Tuple, - List, -) -from abc import abstractmethod - -import cgi - -from azure.core.exceptions import HttpResponseError -from azure.core.pipeline.transport import ( - HttpRequest as _PipelineTransportHttpRequest, -) - -from azure.core.pipeline.transport._base import ( - _HttpResponseBase as _PipelineTransportHttpResponseBase, -) - -from azure.core._pipeline_client import PipelineClient as _PipelineClient -from azure.core._pipeline_client_async import ( - AsyncPipelineClient as _AsyncPipelineClient, -) - -################################### TYPES SECTION ######################### - -ByteStream = Union[Iterable[bytes], AsyncIterable[bytes]] -PrimitiveData = Optional[Union[str, int, float, bool]] - - -ParamsType = Union[ - Mapping[str, Union[PrimitiveData, Sequence[PrimitiveData]]], - List[Tuple[str, PrimitiveData]], -] - -HeadersType = Union[Mapping[str, str], Sequence[Tuple[str, str]]] - -ContentType = Union[str, bytes, ByteStream] - -FileContent = Union[str, bytes, IO[str], IO[bytes]] -FileType = Union[ - Tuple[Optional[str], FileContent], -] - -FilesType = Union[Mapping[str, FileType], Sequence[Tuple[str, FileType]]] - - - -class HttpVerbs(str, Enum): - GET = "GET" - PUT = "PUT" - POST = "POST" - HEAD = "HEAD" - PATCH = "PATCH" - DELETE = "DELETE" - MERGE = "MERGE" - - -########################### UTILS SECTION ################################# - - -def _is_stream_or_str_bytes(content: Any) -> bool: - return isinstance(content, (str, bytes)) or any( - hasattr(content, attr) for attr in ["read", "__iter__", "__aiter__"] - ) - - -def _lookup_encoding(encoding: str) -> bool: - # including check for whether encoding is known taken from httpx - try: - codecs.lookup(encoding) - return True - except LookupError: - return False - - -def _set_content_length_header( - header_name: str, header_value: str, internal_request: _PipelineTransportHttpRequest -) -> None: - valid_methods = ["put", "post", "patch"] - content_length_headers = ["Content-Length", "Transfer-Encoding"] - if internal_request.method.lower() in valid_methods and not any( - [c for c in content_length_headers if c in internal_request.headers] - ): - internal_request.headers[header_name] = header_value - - -def _set_content_type_header( - header_value: str, internal_request: _PipelineTransportHttpRequest -) -> None: - if not internal_request.headers.get("Content-Type"): - internal_request.headers["Content-Type"] = header_value - - -def _set_content_body( - content: ContentType, internal_request: _PipelineTransportHttpRequest -) -> None: - headers = internal_request.headers - content_type = headers.get("Content-Type") - if _is_stream_or_str_bytes(content): - # stream will be bytes / str, or iterator of bytes / str - internal_request.set_streamed_data_body(content) - if isinstance(content, str) and content: - _set_content_length_header( - "Content-Length", str(len(internal_request.data)), internal_request - ) - _set_content_type_header("text/plain", internal_request) - elif isinstance(content, bytes) and content: - _set_content_length_header( - "Content-Length", str(len(internal_request.data)), internal_request - ) - _set_content_type_header("application/octet-stream", internal_request) - elif isinstance(content, (Iterable, AsyncIterable)): # pylint: disable=isinstance-second-argument-not-valid-type - # _set_content_length_header("Transfer-Encoding", "chunked", internal_request) - _set_content_type_header("application/octet-stream", internal_request) - elif isinstance(content, ET.Element): - # XML body - internal_request.set_xml_body(content) - _set_content_type_header("application/xml", internal_request) - _set_content_length_header( - "Content-Length", str(len(internal_request.data)), internal_request - ) - elif content_type and content_type.startswith("text/"): - # Text body - internal_request.set_text_body(content) - _set_content_length_header( - "Content-Length", str(len(internal_request.data)), internal_request - ) - else: - # Other body - internal_request.data = content - internal_request.headers = headers - - -def _set_body( - content: ContentType, - data: dict, - files: Any, - json_body: Any, - internal_request: _PipelineTransportHttpRequest, -) -> None: - if data is not None and not isinstance(data, dict): - content = data - data = None - if content is not None: - _set_content_body(content, internal_request) - elif json_body is not None: - internal_request.set_json_body(json_body) - _set_content_type_header("application/json", internal_request) - elif files is not None: - internal_request.set_formdata_body(files) - # if you don't supply your content type, we'll create a boundary for you with multipart/form-data - # boundary = binascii.hexlify(os.urandom(16)).decode( - # "ascii" - #) # got logic from httpx, thanks httpx! - # _set_content_type_header("multipart/form-data; boundary={}".format(boundary), internal_request) - elif data: - _set_content_type_header("application/x-www-form-urlencoded", internal_request) - internal_request.set_formdata_body(data) - # need to set twice because Content-Type is being popped in set_formdata_body - # don't want to risk changing pipeline.transport, so doing twice here - _set_content_type_header("application/x-www-form-urlencoded", internal_request) - - -def _parse_lines_from_text(text): - # largely taken from httpx's LineDecoder code - lines = [] - last_chunk_of_text = "" - while text: - text_length = len(text) - for idx in range(text_length): - curr_char = text[idx] - next_char = None if idx == len(text) - 1 else text[idx + 1] - if curr_char == "\n": - lines.append(text[: idx + 1]) - text = text[idx + 1 :] - break - if curr_char == "\r" and next_char == "\n": - # if it ends with \r\n, we only do \n - lines.append(text[:idx] + "\n") - text = text[idx + 2 :] - break - if curr_char == "\r" and next_char is not None: - # if it's \r then a normal character, we switch \r to \n - lines.append(text[:idx] + "\n") - text = text[idx + 1 :] - break - if next_char is None: - text = "" - last_chunk_of_text += text - break - if last_chunk_of_text.endswith("\r"): - # if ends with \r, we switch \r to \n - lines.append(last_chunk_of_text[:-1] + "\n") - elif last_chunk_of_text: - lines.append(last_chunk_of_text) - return lines - - -class _StreamContextManagerBase: - def __init__( - self, - client: Union[_PipelineClient, _AsyncPipelineClient], - request: "HttpRequest", - **kwargs - ): - """Used so we can treat stream requests and responses as a context manager. - - In Autorest, we only return a `StreamContextManager` if users pass in `stream_response` True - - Actually sends request when we enter the context manager, closes response when we exit. - - Heavily inspired from httpx, we want the same behavior for it to feel consistent for users - """ - self.client = client - self.request = request - self.kwargs = kwargs - - @abstractmethod - def close(self): - ... - - -class _StreamContextManager(_StreamContextManagerBase): - def __enter__(self) -> "HttpResponse": - """Actually make the call only when we enter. For sync stream_response calls""" - pipeline_transport_response = self.client._pipeline.run( - self.request._internal_request, stream=True, **self.kwargs - ).http_response - self.response = HttpResponse( # pylint: disable=attribute-defined-outside-init - request=self.request, _internal_response=pipeline_transport_response - ) - return self.response - - def __exit__(self, *args): - """Close our stream connection. For sync calls""" - self.response.__exit__(*args) - - def close(self): - self.response.close() - - -class _AsyncStreamContextManager(_StreamContextManagerBase): - async def __aenter__(self) -> "AsyncHttpResponse": - """Actually make the call only when we enter. For async stream_response calls.""" - if not isinstance(self.client, _AsyncPipelineClient): - raise TypeError( - "Only sync calls should enter here. If you mean to do a sync call, " - "make sure to use 'with' instead." - ) - pipeline_transport_response = ( - await self.client._pipeline.run( - self.request._internal_request, stream=True, **self.kwargs - ) - ).http_response - self.response = AsyncHttpResponse( # pylint: disable=attribute-defined-outside-init - request=self.request, _internal_response=pipeline_transport_response - ) - return self.response - - async def __aexit__(self, *args): - await self.response.__aexit__(*args) - - async def close(self): # pylint: disable=invalid-overridden-method - await self.response.close() - - -################################## CLASSES ###################################### - - -class HttpRequest: - """Represents an HTTP request. - - :param method: HTTP method (GET, HEAD, etc.) - :type method: str or ~azure.core.protocol.HttpVerbs - :param str url: The url for your request - :keyword params: Query parameters to be mapped into your URL. Your input - should be a mapping or sequence of query name to query value(s). - :paramtype params: mapping or sequence - :keyword headers: HTTP headers you want in your request. Your input should - be a mapping or sequence of header name to header value. - :paramtype headers: mapping or sequence - :keyword any json: A JSON serializable object. We handle JSON-serialization for your - object, so use this for more complicated data structures than `data`. - :keyword content: Content you want in your request body. Think of it as the kwarg you should input - if your data doesn't fit into `json`, `data`, or `files`. Accepts a bytes type, or a generator - that yields bytes. - :paramtype content: str or bytes or iterable[bytes] or asynciterable[bytes] - :keyword dict data: Form data you want in your request body. Use for form-encoded data, i.e. - HTML forms. - :keyword files: Files you want to in your request body. Use for uploading files with - multipart encoding. Your input should be a mapping or sequence of file name to file content. - Use the `data` kwarg in addition if you want to include non-file data files as part of your request. - :paramtype files: mapping or sequence - :ivar str url: The URL this request is against. - :ivar str method: The method type of this request. - :ivar headers: The HTTP headers you passed in to your request - :vartype headers: mapping or sequence - :ivar bytes content: The content passed in for the request - """ - - def __init__( - self, - method: str, - url: str, - *, - params: Optional[ParamsType] = None, - headers: Optional[HeadersType] = None, - json: Any = None, # pylint: disable=redefined-outer-name - content: Optional[ContentType] = None, - data: Optional[dict] = None, - files: Optional[FilesType] = None, - **kwargs - ): - # type: (str, str, Any) -> None - - self._internal_request = kwargs.pop( - "_internal_request", - _PipelineTransportHttpRequest( - method=method, - url=url, - headers=headers, - ), - ) - - if params: - self._internal_request.format_parameters(params) - - _set_body( - content=content, - data=data, - files=files, - json_body=json, - internal_request=self._internal_request, - ) - - if kwargs: - raise TypeError( - "You have passed in kwargs '{}' that are not valid kwargs.".format( - "', '".join(list(kwargs.keys())) - ) - ) - - def _set_content_length_header(self) -> None: - method_check = self._internal_request.method.lower() in ["put", "post", "patch"] - content_length_unset = "Content-Length" not in self._internal_request.headers - if method_check and content_length_unset: - self._internal_request.headers["Content-Length"] = str( - len(self._internal_request.data) - ) - - @property - def url(self) -> str: - return self._internal_request.url - - @url.setter - def url(self, val: str) -> None: - self._internal_request.url = val - - @property - def method(self) -> str: - return self._internal_request.method - - @property - def headers(self) -> HeadersType: - return self._internal_request.headers - - @property - def content(self) -> Any: - """Gets the request content.""" - return self._internal_request.data or self._internal_request.files - - def __repr__(self) -> str: - return self._internal_request.__repr__() - - def __deepcopy__(self, memo=None) -> "HttpRequest": - return HttpRequest( - self.method, - self.url, - _internal_request=self._internal_request.__deepcopy__(memo), - ) - - -class _HttpResponseBase: - """Base class for HttpResponse and AsyncHttpResponse. - - :keyword request: The request that resulted in this response. - :paramtype request: ~azure.core.rest.HttpRequest - :ivar int status_code: The status code of this response - :ivar headers: The response headers - :vartype headers: dict[str, any] - :ivar str reason: The reason phrase for this response - :ivar bytes content: The response content in bytes - :ivar str url: The URL that resulted in this response - :ivar str encoding: The response encoding. Is settable, by default - is the response Content-Type header - :ivar str text: The response body as a string. - :ivar request: The request that resulted in this response. - :vartype request: ~azure.core.rest.HttpRequest - :ivar str content_type: The content type of the response - :ivar bool is_closed: Whether the network connection has been closed yet - :ivar bool is_stream_consumed: When getting a stream response, checks - whether the stream has been fully consumed - :ivar int num_bytes_downloaded: The number of bytes in your stream that - have been downloaded - """ - - def __init__(self, *, request: HttpRequest, **kwargs): - self._internal_response = kwargs.pop( - "_internal_response" - ) # type: _PipelineTransportHttpResponseBase - self._request = request - self.is_closed = False - self.is_stream_consumed = False - self._num_bytes_downloaded = 0 - - @property - def status_code(self) -> int: - """Returns the status code of the response""" - return self._internal_response.status_code - - @status_code.setter - def status_code(self, val: int) -> None: - """Set the status code of the response""" - self._internal_response.status_code = val - - @property - def headers(self) -> HeadersType: - """Returns the response headers""" - return self._internal_response.headers - - @property - def reason(self) -> str: - """Returns the reason phrase for the response""" - return self._internal_response.reason - - @property - def content(self) -> bytes: - """Returns the response content in bytes""" - raise NotImplementedError() - - @property - def url(self) -> str: - """Returns the URL that resulted in this response""" - return self._internal_response.request.url - - @property - def encoding(self) -> str: - """Returns the response encoding. By default, is specified - by the response Content-Type header. - """ - - try: - return self._encoding - except AttributeError: - return self._get_charset_encoding() - - def _get_charset_encoding(self) -> str: - content_type = self.headers.get("Content-Type") - - if not content_type: - return None - _, params = cgi.parse_header(content_type) - encoding = params.get("charset") # -> utf-8 - if encoding is None or not _lookup_encoding(encoding): - return None - return encoding - - @encoding.setter - def encoding(self, value: str) -> None: - # type: (str) -> None - """Sets the response encoding""" - self._encoding = value - - @property - def text(self) -> str: - """Returns the response body as a string""" - _ = self.content # access content to make sure we trigger if response not fully read in - return self._internal_response.text(encoding=self.encoding) - - @property - def request(self) -> HttpRequest: - if self._request: - return self._request - raise RuntimeError( - "You are trying to access the 'request', but there is no request associated with this HttpResponse" - ) - - @request.setter - def request(self, val: HttpRequest) -> None: - self._request = val - - @property - def content_type(self) -> Optional[str]: - """Content Type of the response""" - return self._internal_response.content_type or self.headers.get("Content-Type") - - @property - def num_bytes_downloaded(self) -> int: - """See how many bytes of your stream response have been downloaded""" - return self._num_bytes_downloaded - - def json(self) -> Any: - """Returns the whole body as a json object. - - :return: The JSON deserialized response body - :rtype: any - :raises json.decoder.JSONDecodeError or ValueError (in python 2.7) if object is not JSON decodable: - """ - return json.loads(self.text) - - def raise_for_status(self) -> None: - """Raises an HttpResponseError if the response has an error status code. - - If response is good, does nothing. - """ - if self.status_code >= 400: - raise HttpResponseError(response=self) - - def __repr__(self) -> str: - content_type_str = ( - ", Content-Type: {}".format(self.content_type) if self.content_type else "" - ) - return "<{}: {} {}{}>".format( - type(self).__name__, self.status_code, self.reason, content_type_str - ) - - def _validate_streaming_access(self) -> None: - if self.is_closed: - raise ResponseClosedError() - if self.is_stream_consumed: - raise StreamConsumedError() - - -class HttpResponse(_HttpResponseBase): - @property - def content(self): - # type: (...) -> bytes - try: - return self._content - except AttributeError: - raise ResponseNotReadError() - - def close(self) -> None: - self.is_closed = True - self._internal_response.internal_response.close() - - def __exit__(self, *args) -> None: - self._internal_response.internal_response.__exit__(*args) - - def read(self) -> bytes: - """ - Read the response's bytes. - - """ - try: - return self._content - except AttributeError: - self._validate_streaming_access() - self._content = (self._internal_response.body() or # pylint: disable=attribute-defined-outside-init - b"".join(self.iter_raw())) - self._close_stream() - return self._content - - def iter_bytes(self, chunk_size: int = None) -> Iterator[bytes]: - """Iterate over the bytes in the response stream""" - try: - chunk_size = len(self._content) if chunk_size is None else chunk_size - for i in range(0, len(self._content), chunk_size): - yield self._content[i : i + chunk_size] - - except AttributeError: - for raw_bytes in self.iter_raw(chunk_size=chunk_size): - yield raw_bytes - - def iter_text(self, chunk_size: int = None) -> Iterator[str]: - """Iterate over the response text""" - for byte in self.iter_bytes(chunk_size): - text = byte.decode(self.encoding or "utf-8") - yield text - - def iter_lines(self, chunk_size: int = None) -> Iterator[str]: - for text in self.iter_text(chunk_size): - lines = _parse_lines_from_text(text) - for line in lines: - yield line - - def _close_stream(self) -> None: - self.is_stream_consumed = True - self.close() - - def iter_raw(self, **_) -> Iterator[bytes]: - """Iterate over the raw response bytes""" - self._validate_streaming_access() - stream_download = self._internal_response.stream_download(None) - for raw_bytes in stream_download: - self._num_bytes_downloaded += len(raw_bytes) - yield raw_bytes - - self._close_stream() - - -class AsyncHttpResponse(_HttpResponseBase): - @property - def content(self) -> bytes: - try: - return self._content - except AttributeError: - raise ResponseNotReadError() - - async def _close_stream(self) -> None: - self.is_stream_consumed = True - await self.close() - - async def read(self) -> bytes: - """ - Read the response's bytes. - - """ - try: - return self._content - except AttributeError: - self._validate_streaming_access() - await self._internal_response.load_body() - self._content = self._internal_response._body # pylint: disable=protected-access,attribute-defined-outside-init - await self._close_stream() - return self._content - - async def iter_bytes(self, chunk_size: int = None) -> Iterator[bytes]: - """Iterate over the bytes in the response stream""" - try: - chunk_size = len(self._content) if chunk_size is None else chunk_size - for i in range(0, len(self._content), chunk_size): - yield self._content[i : i + chunk_size] - - except AttributeError: - async for raw_bytes in self.iter_raw(chunk_size=chunk_size): - yield raw_bytes - - async def iter_text(self, chunk_size: int = None) -> Iterator[str]: - """Iterate over the response text""" - async for byte in self.iter_bytes(chunk_size): - text = byte.decode(self.encoding or "utf-8") - yield text - - async def iter_lines(self, chunk_size: int = None) -> Iterator[str]: - async for text in self.iter_text(chunk_size): - lines = _parse_lines_from_text(text) - for line in lines: - yield line - - async def iter_raw(self, **_) -> Iterator[bytes]: - """Iterate over the raw response bytes""" - self._validate_streaming_access() - stream_download = self._internal_response.stream_download(None) - async for raw_bytes in stream_download: - self._num_bytes_downloaded += len(raw_bytes) - yield raw_bytes - - await self._close_stream() - - async def close(self) -> None: - self.is_closed = True - self._internal_response.internal_response.close() - await asyncio.sleep(0) - - async def __aexit__(self, *args) -> None: - await self._internal_response.internal_response.__aexit__(*args) - - -########################### ERRORS SECTION ################################# - - -class StreamConsumedError(Exception): - def __init__(self) -> None: - message = ( - "You are attempting to read or stream content that has already been streamed. " - "You have likely already consumed this stream, so it can not be accessed anymore." - ) - super().__init__(message) - - -class ResponseClosedError(Exception): - def __init__(self) -> None: - message = ( - "You can not try to read or stream this response's content, since the " - "response has been closed." - ) - super().__init__(message) - - -class ResponseNotReadError(Exception): - def __init__(self) -> None: - message = ( - "You have not read in the response's bytes yet. Call response.read() first." - ) - super().__init__(message) diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/operations/__init__.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/operations/__init__.py new file mode 100644 index 000000000000..af83bc4323b2 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/operations/__init__.py @@ -0,0 +1,13 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from ._operations import WebPubSubServiceClientOperationsMixin + +__all__ = [ + 'WebPubSubServiceClientOperationsMixin', +] diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/operations/_operations.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/operations/_operations.py new file mode 100644 index 000000000000..f67786c1052d --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/operations/_operations.py @@ -0,0 +1,1724 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import functools +from typing import TYPE_CHECKING +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import HttpResponse +from azure.core.pipeline.transport._base import _format_url_section +from azure.core.rest import HttpRequest +from azure.core.tracing.decorator import distributed_trace +from msrest import Serializer + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any, Callable, Dict, Generic, IO, List, Optional, TypeVar, Union + + T = TypeVar('T') + ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] + +_SERIALIZER = Serializer() +# fmt: off + +def build_generate_client_token_request( + hub, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + user_id = kwargs.pop('user_id', "") # type: Optional[str] + role = kwargs.pop('role', None) # type: Optional[List[str]] + minutes_to_expire = kwargs.pop('minutes_to_expire', 60) # type: Optional[int] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + accept = "application/json, text/json" + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/:generateToken') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if user_id is not None: + query_parameters['userId'] = _SERIALIZER.query("user_id", user_id, 'str') + if role is not None: + query_parameters['role'] = [_SERIALIZER.query("role", q, 'str') if q is not None else '' for q in role] + if minutes_to_expire is not None: + query_parameters['minutesToExpire'] = _SERIALIZER.query("minutes_to_expire", minutes_to_expire, 'int') + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + # Construct headers + header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] + header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str') + + return HttpRequest( + method="POST", + url=url, + params=query_parameters, + headers=header_parameters, + **kwargs + ) + + +def build_send_to_all_request( + hub, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + content_type = kwargs.pop('content_type', None) # type: Optional[str] + excluded = kwargs.pop('excluded', None) # type: Optional[List[str]] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/:send') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if excluded is not None: + query_parameters['excluded'] = [_SERIALIZER.query("excluded", q, 'str') if q is not None else '' for q in excluded] + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + # Construct headers + header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] + if content_type is not None: + header_parameters['Content-Type'] = _SERIALIZER.header("content_type", content_type, 'str') + + return HttpRequest( + method="POST", + url=url, + params=query_parameters, + headers=header_parameters, + **kwargs + ) + + +def build_connection_exists_request( + hub, # type: str + connection_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/connections/{connectionId}') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "connectionId": _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + return HttpRequest( + method="HEAD", + url=url, + params=query_parameters, + **kwargs + ) + + +def build_close_connection_request( + hub, # type: str + connection_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + reason = kwargs.pop('reason', None) # type: Optional[str] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/connections/{connectionId}') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "connectionId": _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if reason is not None: + query_parameters['reason'] = _SERIALIZER.query("reason", reason, 'str') + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + return HttpRequest( + method="DELETE", + url=url, + params=query_parameters, + **kwargs + ) + + +def build_send_to_connection_request( + hub, # type: str + connection_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + content_type = kwargs.pop('content_type', None) # type: Optional[str] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/connections/{connectionId}/:send') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "connectionId": _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + # Construct headers + header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] + if content_type is not None: + header_parameters['Content-Type'] = _SERIALIZER.header("content_type", content_type, 'str') + + return HttpRequest( + method="POST", + url=url, + params=query_parameters, + headers=header_parameters, + **kwargs + ) + + +def build_group_exists_request( + hub, # type: str + group, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/groups/{group}') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "group": _SERIALIZER.url("group", group, 'str', max_length=1024, min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + return HttpRequest( + method="HEAD", + url=url, + params=query_parameters, + **kwargs + ) + + +def build_send_to_group_request( + hub, # type: str + group, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + content_type = kwargs.pop('content_type', None) # type: Optional[str] + excluded = kwargs.pop('excluded', None) # type: Optional[List[str]] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/groups/{group}/:send') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "group": _SERIALIZER.url("group", group, 'str', max_length=1024, min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if excluded is not None: + query_parameters['excluded'] = [_SERIALIZER.query("excluded", q, 'str') if q is not None else '' for q in excluded] + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + # Construct headers + header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] + if content_type is not None: + header_parameters['Content-Type'] = _SERIALIZER.header("content_type", content_type, 'str') + + return HttpRequest( + method="POST", + url=url, + params=query_parameters, + headers=header_parameters, + **kwargs + ) + + +def build_add_connection_to_group_request( + hub, # type: str + group, # type: str + connection_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/groups/{group}/connections/{connectionId}') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "group": _SERIALIZER.url("group", group, 'str', max_length=1024, min_length=1), + "connectionId": _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + return HttpRequest( + method="PUT", + url=url, + params=query_parameters, + **kwargs + ) + + +def build_remove_connection_from_group_request( + hub, # type: str + group, # type: str + connection_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/groups/{group}/connections/{connectionId}') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "group": _SERIALIZER.url("group", group, 'str', max_length=1024, min_length=1), + "connectionId": _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + return HttpRequest( + method="DELETE", + url=url, + params=query_parameters, + **kwargs + ) + + +def build_user_exists_request( + hub, # type: str + user_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/users/{userId}') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "userId": _SERIALIZER.url("user_id", user_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + return HttpRequest( + method="HEAD", + url=url, + params=query_parameters, + **kwargs + ) + + +def build_send_to_user_request( + hub, # type: str + user_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + content_type = kwargs.pop('content_type', None) # type: Optional[str] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/users/{userId}/:send') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "userId": _SERIALIZER.url("user_id", user_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + # Construct headers + header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] + if content_type is not None: + header_parameters['Content-Type'] = _SERIALIZER.header("content_type", content_type, 'str') + + return HttpRequest( + method="POST", + url=url, + params=query_parameters, + headers=header_parameters, + **kwargs + ) + + +def build_add_user_to_group_request( + hub, # type: str + group, # type: str + user_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/users/{userId}/groups/{group}') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "group": _SERIALIZER.url("group", group, 'str', max_length=1024, min_length=1), + "userId": _SERIALIZER.url("user_id", user_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + return HttpRequest( + method="PUT", + url=url, + params=query_parameters, + **kwargs + ) + + +def build_remove_user_from_group_request( + hub, # type: str + group, # type: str + user_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/users/{userId}/groups/{group}') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "group": _SERIALIZER.url("group", group, 'str', max_length=1024, min_length=1), + "userId": _SERIALIZER.url("user_id", user_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + return HttpRequest( + method="DELETE", + url=url, + params=query_parameters, + **kwargs + ) + + +def build_remove_user_from_all_groups_request( + hub, # type: str + user_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/users/{userId}/groups') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "userId": _SERIALIZER.url("user_id", user_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + return HttpRequest( + method="DELETE", + url=url, + params=query_parameters, + **kwargs + ) + + +def build_grant_permission_request( + hub, # type: str + permission, # type: str + connection_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + target_name = kwargs.pop('target_name', None) # type: Optional[str] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "permission": _SERIALIZER.url("permission", permission, 'str'), + "connectionId": _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if target_name is not None: + query_parameters['targetName'] = _SERIALIZER.query("target_name", target_name, 'str') + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + return HttpRequest( + method="PUT", + url=url, + params=query_parameters, + **kwargs + ) + + +def build_revoke_permission_request( + hub, # type: str + permission, # type: str + connection_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + target_name = kwargs.pop('target_name', None) # type: Optional[str] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "permission": _SERIALIZER.url("permission", permission, 'str'), + "connectionId": _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if target_name is not None: + query_parameters['targetName'] = _SERIALIZER.query("target_name", target_name, 'str') + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + return HttpRequest( + method="DELETE", + url=url, + params=query_parameters, + **kwargs + ) + + +def build_check_permission_request( + hub, # type: str + permission, # type: str + connection_id, # type: str + **kwargs # type: Any +): + # type: (...) -> HttpRequest + target_name = kwargs.pop('target_name', None) # type: Optional[str] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + # Construct URL + url = kwargs.pop("template_url", '/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}') + path_format_arguments = { + "hub": _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), + "permission": _SERIALIZER.url("permission", permission, 'str'), + "connectionId": _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), + } + + url = _format_url_section(url, **path_format_arguments) + + # Construct parameters + query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if target_name is not None: + query_parameters['targetName'] = _SERIALIZER.query("target_name", target_name, 'str') + if api_version is not None: + query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') + + return HttpRequest( + method="HEAD", + url=url, + params=query_parameters, + **kwargs + ) + +# fmt: on +class WebPubSubServiceClientOperationsMixin(object): + + @distributed_trace + def generate_client_token( + self, + hub, # type: str + **kwargs # type: Any + ): + # type: (...) -> Any + """Generate token for the client to connect Azure Web PubSub service. + + Generate token for the client to connect Azure Web PubSub service. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :keyword user_id: User Id. + :paramtype user_id: str + :keyword role: Roles that the connection with the generated token will have. + :paramtype role: list[str] + :keyword minutes_to_expire: The expire time of the generated token. + :paramtype minutes_to_expire: int + :keyword api_version: Api Version. + :paramtype api_version: str + :return: JSON object + :rtype: Any + :raises: ~azure.core.exceptions.HttpResponseError + + Example: + .. code-block:: python + + # response body for status code(s): 200 + response.json() == { + "token": "str (optional)" + } + """ + cls = kwargs.pop('cls', None) # type: ClsType[Any] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + user_id = kwargs.pop('user_id', "") # type: Optional[str] + role = kwargs.pop('role', None) # type: Optional[List[str]] + minutes_to_expire = kwargs.pop('minutes_to_expire', 60) # type: Optional[int] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_generate_client_token_request( + hub=hub, + user_id=user_id, + role=role, + minutes_to_expire=minutes_to_expire, + api_version=api_version, + template_url=self.generate_client_token.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if response.content: + deserialized = response.json() + else: + deserialized = None + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + + generate_client_token.metadata = {'url': '/api/hubs/{hub}/:generateToken'} # type: ignore + + + @distributed_trace + def send_to_all( + self, + hub, # type: str + message, # type: Union[IO, str] + **kwargs # type: Any + ): + # type: (...) -> None + """Broadcast content inside request body to all the connected client connections. + + Broadcast content inside request body to all the connected client connections. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param message: The payload body. + :type message: IO or str + :keyword excluded: Excluded connection Ids. + :paramtype excluded: list[str] + :keyword api_version: Api Version. + :paramtype api_version: str + :keyword str content_type: Media type of the body sent to the API. Default value is + "application/json". Allowed values are: "application/json", "application/octet-stream", + "text/plain." + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + content_type = kwargs.pop('content_type', "text/plain") # type: Optional[str] + excluded = kwargs.pop('excluded', None) # type: Optional[List[str]] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + json = None + content = None + if content_type.split(";")[0] in ['application/json', 'application/octet-stream']: + content = message + elif content_type.split(";")[0] in ['text/plain']: + json = message + else: + raise ValueError( + "The content_type '{}' is not one of the allowed values: " + "['application/json', 'application/octet-stream', 'text/plain']".format(content_type) + ) + + request = build_send_to_all_request( + hub=hub, + content_type=content_type, + excluded=excluded, + api_version=api_version, + json=json, + content=content, + template_url=self.send_to_all.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + send_to_all.metadata = {'url': '/api/hubs/{hub}/:send'} # type: ignore + + + @distributed_trace + def connection_exists( + self, + hub, # type: str + connection_id, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Check if the connection with the given connectionId exists. + + Check if the connection with the given connectionId exists. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param connection_id: The connection Id. + :type connection_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_connection_exists_request( + hub=hub, + connection_id=connection_id, + api_version=api_version, + template_url=self.connection_exists.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + connection_exists.metadata = {'url': '/api/hubs/{hub}/connections/{connectionId}'} # type: ignore + + + @distributed_trace + def close_connection( + self, + hub, # type: str + connection_id, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Close the client connection. + + Close the client connection. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param connection_id: Target connection Id. + :type connection_id: str + :keyword reason: The reason closing the client connection. + :paramtype reason: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + reason = kwargs.pop('reason', None) # type: Optional[str] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_close_connection_request( + hub=hub, + connection_id=connection_id, + reason=reason, + api_version=api_version, + template_url=self.close_connection.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + close_connection.metadata = {'url': '/api/hubs/{hub}/connections/{connectionId}'} # type: ignore + + + @distributed_trace + def send_to_connection( + self, + hub, # type: str + connection_id, # type: str + message, # type: Union[IO, str] + **kwargs # type: Any + ): + # type: (...) -> None + """Send content inside request body to the specific connection. + + Send content inside request body to the specific connection. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param connection_id: The connection Id. + :type connection_id: str + :param message: The payload body. + :type message: IO or str + :keyword api_version: Api Version. + :paramtype api_version: str + :keyword str content_type: Media type of the body sent to the API. Default value is + "application/json". Allowed values are: "application/json", "application/octet-stream", + "text/plain." + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + content_type = kwargs.pop('content_type', "text/plain") # type: Optional[str] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + json = None + content = None + if content_type.split(";")[0] in ['application/json', 'application/octet-stream']: + content = message + elif content_type.split(";")[0] in ['text/plain']: + json = message + else: + raise ValueError( + "The content_type '{}' is not one of the allowed values: " + "['application/json', 'application/octet-stream', 'text/plain']".format(content_type) + ) + + request = build_send_to_connection_request( + hub=hub, + connection_id=connection_id, + content_type=content_type, + api_version=api_version, + json=json, + content=content, + template_url=self.send_to_connection.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + send_to_connection.metadata = {'url': '/api/hubs/{hub}/connections/{connectionId}/:send'} # type: ignore + + + @distributed_trace + def group_exists( + self, + hub, # type: str + group, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Check if there are any client connections inside the given group. + + Check if there are any client connections inside the given group. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param group: Target group name, which length should be greater than 0 and less than 1025. + :type group: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_group_exists_request( + hub=hub, + group=group, + api_version=api_version, + template_url=self.group_exists.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + group_exists.metadata = {'url': '/api/hubs/{hub}/groups/{group}'} # type: ignore + + + @distributed_trace + def send_to_group( + self, + hub, # type: str + group, # type: str + message, # type: Union[IO, str] + **kwargs # type: Any + ): + # type: (...) -> None + """Send content inside request body to a group of connections. + + Send content inside request body to a group of connections. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param group: Target group name, which length should be greater than 0 and less than 1025. + :type group: str + :param message: The payload body. + :type message: IO or str + :keyword excluded: Excluded connection Ids. + :paramtype excluded: list[str] + :keyword api_version: Api Version. + :paramtype api_version: str + :keyword str content_type: Media type of the body sent to the API. Default value is + "application/json". Allowed values are: "application/json", "application/octet-stream", + "text/plain." + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + content_type = kwargs.pop('content_type', "text/plain") # type: Optional[str] + excluded = kwargs.pop('excluded', None) # type: Optional[List[str]] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + json = None + content = None + if content_type.split(";")[0] in ['application/json', 'application/octet-stream']: + content = message + elif content_type.split(";")[0] in ['text/plain']: + json = message + else: + raise ValueError( + "The content_type '{}' is not one of the allowed values: " + "['application/json', 'application/octet-stream', 'text/plain']".format(content_type) + ) + + request = build_send_to_group_request( + hub=hub, + group=group, + content_type=content_type, + excluded=excluded, + api_version=api_version, + json=json, + content=content, + template_url=self.send_to_group.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + send_to_group.metadata = {'url': '/api/hubs/{hub}/groups/{group}/:send'} # type: ignore + + + @distributed_trace + def add_connection_to_group( + self, + hub, # type: str + group, # type: str + connection_id, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Add a connection to the target group. + + Add a connection to the target group. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param group: Target group name, which length should be greater than 0 and less than 1025. + :type group: str + :param connection_id: Target connection Id. + :type connection_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_add_connection_to_group_request( + hub=hub, + group=group, + connection_id=connection_id, + api_version=api_version, + template_url=self.add_connection_to_group.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + add_connection_to_group.metadata = {'url': '/api/hubs/{hub}/groups/{group}/connections/{connectionId}'} # type: ignore + + + @distributed_trace + def remove_connection_from_group( + self, + hub, # type: str + group, # type: str + connection_id, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Remove a connection from the target group. + + Remove a connection from the target group. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param group: Target group name, which length should be greater than 0 and less than 1025. + :type group: str + :param connection_id: Target connection Id. + :type connection_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_remove_connection_from_group_request( + hub=hub, + group=group, + connection_id=connection_id, + api_version=api_version, + template_url=self.remove_connection_from_group.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + remove_connection_from_group.metadata = {'url': '/api/hubs/{hub}/groups/{group}/connections/{connectionId}'} # type: ignore + + + @distributed_trace + def user_exists( + self, + hub, # type: str + user_id, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Check if there are any client connections connected for the given user. + + Check if there are any client connections connected for the given user. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param user_id: Target user Id. + :type user_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_user_exists_request( + hub=hub, + user_id=user_id, + api_version=api_version, + template_url=self.user_exists.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + user_exists.metadata = {'url': '/api/hubs/{hub}/users/{userId}'} # type: ignore + + + @distributed_trace + def send_to_user( + self, + hub, # type: str + user_id, # type: str + message, # type: Union[IO, str] + **kwargs # type: Any + ): + # type: (...) -> None + """Send content inside request body to the specific user. + + Send content inside request body to the specific user. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param user_id: The user Id. + :type user_id: str + :param message: The payload body. + :type message: IO or str + :keyword api_version: Api Version. + :paramtype api_version: str + :keyword str content_type: Media type of the body sent to the API. Default value is + "application/json". Allowed values are: "application/json", "application/octet-stream", + "text/plain." + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + content_type = kwargs.pop('content_type', "text/plain") # type: Optional[str] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + json = None + content = None + if content_type.split(";")[0] in ['application/json', 'application/octet-stream']: + content = message + elif content_type.split(";")[0] in ['text/plain']: + json = message + else: + raise ValueError( + "The content_type '{}' is not one of the allowed values: " + "['application/json', 'application/octet-stream', 'text/plain']".format(content_type) + ) + + request = build_send_to_user_request( + hub=hub, + user_id=user_id, + content_type=content_type, + api_version=api_version, + json=json, + content=content, + template_url=self.send_to_user.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + send_to_user.metadata = {'url': '/api/hubs/{hub}/users/{userId}/:send'} # type: ignore + + + @distributed_trace + def add_user_to_group( + self, + hub, # type: str + group, # type: str + user_id, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Add a user to the target group. + + Add a user to the target group. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param group: Target group name, which length should be greater than 0 and less than 1025. + :type group: str + :param user_id: Target user Id. + :type user_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_add_user_to_group_request( + hub=hub, + group=group, + user_id=user_id, + api_version=api_version, + template_url=self.add_user_to_group.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + add_user_to_group.metadata = {'url': '/api/hubs/{hub}/users/{userId}/groups/{group}'} # type: ignore + + + @distributed_trace + def remove_user_from_group( + self, + hub, # type: str + group, # type: str + user_id, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Remove a user from the target group. + + Remove a user from the target group. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param group: Target group name, which length should be greater than 0 and less than 1025. + :type group: str + :param user_id: Target user Id. + :type user_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_remove_user_from_group_request( + hub=hub, + group=group, + user_id=user_id, + api_version=api_version, + template_url=self.remove_user_from_group.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + remove_user_from_group.metadata = {'url': '/api/hubs/{hub}/users/{userId}/groups/{group}'} # type: ignore + + + @distributed_trace + def remove_user_from_all_groups( + self, + hub, # type: str + user_id, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Remove a user from all groups. + + Remove a user from all groups. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param user_id: Target user Id. + :type user_id: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_remove_user_from_all_groups_request( + hub=hub, + user_id=user_id, + api_version=api_version, + template_url=self.remove_user_from_all_groups.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + remove_user_from_all_groups.metadata = {'url': '/api/hubs/{hub}/users/{userId}/groups'} # type: ignore + + + @distributed_trace + def grant_permission( + self, + hub, # type: str + permission, # type: str + connection_id, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Grant permission to the connection. + + Grant permission to the connection. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param permission: The permission: current supported actions are joinLeaveGroup and + sendToGroup. Possible values are: "sendToGroup" or "joinLeaveGroup". + :type permission: str + :param connection_id: Target connection Id. + :type connection_id: str + :keyword target_name: The meaning of the target depends on the specific permission. For + joinLeaveGroup and sendToGroup, targetName is a required parameter standing for the group name. + :paramtype target_name: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + target_name = kwargs.pop('target_name', None) # type: Optional[str] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_grant_permission_request( + hub=hub, + permission=permission, + connection_id=connection_id, + target_name=target_name, + api_version=api_version, + template_url=self.grant_permission.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + grant_permission.metadata = {'url': '/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}'} # type: ignore + + + @distributed_trace + def revoke_permission( + self, + hub, # type: str + permission, # type: str + connection_id, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Revoke permission for the connection. + + Revoke permission for the connection. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param permission: The permission: current supported actions are joinLeaveGroup and + sendToGroup. Possible values are: "sendToGroup" or "joinLeaveGroup". + :type permission: str + :param connection_id: Target connection Id. + :type connection_id: str + :keyword target_name: The meaning of the target depends on the specific permission. For + joinLeaveGroup and sendToGroup, targetName is a required parameter standing for the group name. + :paramtype target_name: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + target_name = kwargs.pop('target_name', None) # type: Optional[str] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_revoke_permission_request( + hub=hub, + permission=permission, + connection_id=connection_id, + target_name=target_name, + api_version=api_version, + template_url=self.revoke_permission.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + revoke_permission.metadata = {'url': '/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}'} # type: ignore + + + @distributed_trace + def check_permission( + self, + hub, # type: str + permission, # type: str + connection_id, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Check if a connection has permission to the specified action. + + Check if a connection has permission to the specified action. + + :param hub: Target hub name, which should start with alphabetic characters and only contain + alpha-numeric characters or underscore. + :type hub: str + :param permission: The permission: current supported actions are joinLeaveGroup and + sendToGroup. Possible values are: "sendToGroup" or "joinLeaveGroup". + :type permission: str + :param connection_id: Target connection Id. + :type connection_id: str + :keyword target_name: The meaning of the target depends on the specific permission. For + joinLeaveGroup and sendToGroup, targetName is a required parameter standing for the group name. + :paramtype target_name: str + :keyword api_version: Api Version. + :paramtype api_version: str + :return: None + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + target_name = kwargs.pop('target_name', None) # type: Optional[str] + api_version = kwargs.pop('api_version', "2021-08-01-preview") # type: Optional[str] + + + request = build_check_permission_request( + hub=hub, + permission=permission, + connection_id=connection_id, + target_name=target_name, + api_version=api_version, + template_url=self.check_permission.metadata['url'], + ) + path_format_arguments = { + "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) + + pipeline_response = self._client.send_request(request, stream=False, _return_pipeline_response=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) + + check_permission.metadata = {'url': '/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}'} # type: ignore + diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/py.typed b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/py.typed new file mode 100644 index 000000000000..e5aff4f83af8 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561. \ No newline at end of file diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/rest.py b/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/rest.py deleted file mode 100644 index 9d57abd5a1c0..000000000000 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/azure/messaging/webpubsubservice/rest.py +++ /dev/null @@ -1,942 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- - -# pylint: disable=line-too-long - -__all__ = [ - 'build_add_connection_to_group_request', - 'build_add_user_to_group_request', - 'build_connection_exists_request', - 'build_group_exists_request', - 'build_check_permission_request', - 'build_user_exists_request', - 'build_close_client_connection_request', - 'build_grant_permission_request', - 'build_healthapi_get_health_status_request', - 'build_remove_connection_from_group_request', - 'build_remove_user_from_all_groups_request', - 'build_remove_user_from_group_request', - 'build_revoke_permission_request', - 'build_send_to_all_request', - 'build_send_to_connection_request', - 'build_send_to_group_request', - 'build_send_to_user_request' -] -from typing import TYPE_CHECKING -from msrest import Serializer -from azure.core.pipeline.transport._base import _format_url_section -from azure.messaging.webpubsubservice.core.rest import HttpRequest - -if TYPE_CHECKING: - # pylint: disable=unused-import,ungrouped-imports - from typing import Any, IO, List, Optional, Union, Dict - from typing_extensions import Literal - Permissions = Union[Literal['joinLeaveGroup'], Literal['sendToGroup']] # pylint: disable=unsubscriptable-object - -_SERIALIZER = Serializer() - - -def build_healthapi_get_health_status_request( - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Get service health status. - - Get service health status. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/health') - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="HEAD", - url=url, - params=query_parameters, - **kwargs - ) - - -def build_send_to_all_request( - hub, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Broadcast content inside request body to all the connected client connections. - - Broadcast content inside request body to all the connected client connections. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :keyword json: The payload body. - :paramtype json: Any - :keyword content: The payload body. - :paramtype content: IO - :keyword excluded: Excluded connection Ids. - :paramtype excluded: list[str] - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - - Example: - .. code-block:: python - - # JSON input template you can fill out and use as your `json` input. - json = "Any (optional)" - """ - excluded = kwargs.pop('excluded', None) # type: Optional[List[str]] - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - content_type = kwargs.pop("content_type", None) - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/:send') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if excluded is not None: - query_parameters['excluded'] = [_SERIALIZER.query("excluded", q, 'str') if q is not None else '' for q in excluded] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - # Construct headers - header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] - if content_type is not None: - header_parameters['Content-Type'] = _SERIALIZER.header("content_type", content_type, 'str') - - return HttpRequest( - method="POST", - url=url, - params=query_parameters, - headers=header_parameters, - **kwargs - ) - - -def build_connection_exists_request( - hub, # type: str - connection_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Check if the connection with the given connectionId exists. - - Check if the connection with the given connectionId exists. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param connection_id: The connection Id. - :type connection_id: str - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/connections/{connectionId}') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'connectionId': _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="HEAD", - url=url, - params=query_parameters, - **kwargs - ) - - -def build_close_client_connection_request( - hub, # type: str - connection_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Close the client connection. - - Close the client connection. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param connection_id: Target connection Id. - :type connection_id: str - :keyword reason: The reason closing the client connection. - :paramtype reason: str - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - reason = kwargs.pop('reason', None) # type: Optional[str] - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/connections/{connectionId}') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'connectionId': _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if reason is not None: - query_parameters['reason'] = _SERIALIZER.query("reason", reason, 'str') - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="DELETE", - url=url, - params=query_parameters, - **kwargs - ) - - -def build_send_to_connection_request( - hub, # type: str - connection_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Send content inside request body to the specific connection. - - Send content inside request body to the specific connection. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param connection_id: The connection Id. - :type connection_id: str - :keyword json: The payload body. - :paramtype json: Any - :keyword content: The payload body. - :paramtype content: IO - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - - Example: - .. code-block:: python - - # JSON input template you can fill out and use as your `json` input. - json = "Any (optional)" - """ - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - content_type = kwargs.pop("content_type", None) - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/connections/{connectionId}/:send') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'connectionId': _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - # Construct headers - header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] - if content_type is not None: - header_parameters['Content-Type'] = _SERIALIZER.header("content_type", content_type, 'str') - - return HttpRequest( - method="POST", - url=url, - params=query_parameters, - headers=header_parameters, - **kwargs - ) - - -def build_group_exists_request( - hub, # type: str - group, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Check if there are any client connections inside the given group. - - Check if there are any client connections inside the given group. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param group: Target group name, which length should be greater than 0 and less than 1025. - :type group: str - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/groups/{group}') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'group': _SERIALIZER.url("group", group, 'str', max_length=1024, min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="HEAD", - url=url, - params=query_parameters, - **kwargs - ) - - -def build_send_to_group_request( - hub, # type: str - group, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Send content inside request body to a group of connections. - - Send content inside request body to a group of connections. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param group: Target group name, which length should be greater than 0 and less than 1025. - :type group: str - :keyword json: The payload body. - :paramtype json: Any - :keyword content: The payload body. - :paramtype content: IO - :keyword excluded: Excluded connection Ids. - :paramtype excluded: list[str] - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - - Example: - .. code-block:: python - - # JSON input template you can fill out and use as your `json` input. - json = "Any (optional)" - """ - excluded = kwargs.pop('excluded', None) # type: Optional[List[str]] - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - content_type = kwargs.pop("content_type", None) - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/groups/{group}/:send') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'group': _SERIALIZER.url("group", group, 'str', max_length=1024, min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if excluded is not None: - query_parameters['excluded'] = [_SERIALIZER.query("excluded", q, 'str') if q is not None else '' for q in excluded] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - # Construct headers - header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] - if content_type is not None: - header_parameters['Content-Type'] = _SERIALIZER.header("content_type", content_type, 'str') - - return HttpRequest( - method="POST", - url=url, - params=query_parameters, - headers=header_parameters, - **kwargs - ) - - -def build_add_connection_to_group_request( - hub, # type: str - group, # type: str - connection_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Add a connection to the target group. - - Add a connection to the target group. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param group: Target group name, which length should be greater than 0 and less than 1025. - :type group: str - :param connection_id: Target connection Id. - :type connection_id: str - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/groups/{group}/connections/{connectionId}') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'group': _SERIALIZER.url("group", group, 'str', max_length=1024, min_length=1), - 'connectionId': _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="PUT", - url=url, - params=query_parameters, - **kwargs - ) - - -def build_remove_connection_from_group_request( - hub, # type: str - group, # type: str - connection_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Remove a connection from the target group. - - Remove a connection from the target group. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param group: Target group name, which length should be greater than 0 and less than 1025. - :type group: str - :param connection_id: Target connection Id. - :type connection_id: str - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/groups/{group}/connections/{connectionId}') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'group': _SERIALIZER.url("group", group, 'str', max_length=1024, min_length=1), - 'connectionId': _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="DELETE", - url=url, - params=query_parameters, - **kwargs - ) - - -def build_user_exists_request( - hub, # type: str - user_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Check if there are any client connections connected for the given user. - - Check if there are any client connections connected for the given user. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param user_id: Target user Id. - :type user_id: str - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/users/{userId}') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'userId': _SERIALIZER.url("user_id", user_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="HEAD", - url=url, - params=query_parameters, - **kwargs - ) - - -def build_send_to_user_request( - hub, # type: str - user_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Send content inside request body to the specific user. - - Send content inside request body to the specific user. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param user_id: The user Id. - :type user_id: str - :keyword json: The payload body. - :paramtype json: Any - :keyword content: The payload body. - :paramtype content: IO - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - - Example: - .. code-block:: python - - # JSON input template you can fill out and use as your `json` input. - json = "Any (optional)" - """ - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - content_type = kwargs.pop("content_type", None) - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/users/{userId}/:send') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'userId': _SERIALIZER.url("user_id", user_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - # Construct headers - header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] - if content_type is not None: - header_parameters['Content-Type'] = _SERIALIZER.header("content_type", content_type, 'str') - - return HttpRequest( - method="POST", - url=url, - params=query_parameters, - headers=header_parameters, - **kwargs - ) - - -def build_add_user_to_group_request( - hub, # type: str - group, # type: str - user_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Add a user to the target group. - - Add a user to the target group. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param group: Target group name, which length should be greater than 0 and less than 1025. - :type group: str - :param user_id: Target user Id. - :type user_id: str - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/users/{userId}/groups/{group}') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'group': _SERIALIZER.url("group", group, 'str', max_length=1024, min_length=1), - 'userId': _SERIALIZER.url("user_id", user_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="PUT", - url=url, - params=query_parameters, - **kwargs - ) - - -def build_remove_user_from_group_request( - hub, # type: str - group, # type: str - user_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Remove a user from the target group. - - Remove a user from the target group. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param group: Target group name, which length should be greater than 0 and less than 1025. - :type group: str - :param user_id: Target user Id. - :type user_id: str - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/users/{userId}/groups/{group}') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'group': _SERIALIZER.url("group", group, 'str', max_length=1024, min_length=1), - 'userId': _SERIALIZER.url("user_id", user_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="DELETE", - url=url, - params=query_parameters, - **kwargs - ) - - -def build_remove_user_from_all_groups_request( - hub, # type: str - user_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Remove a user from all groups. - - Remove a user from all groups. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param user_id: Target user Id. - :type user_id: str - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/users/{userId}/groups') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'userId': _SERIALIZER.url("user_id", user_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="DELETE", - url=url, - params=query_parameters, - **kwargs - ) - - -def build_grant_permission_request( - hub, # type: str - permission, # type: Permissions - connection_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Grant permission to the connection. - - Grant permission to the connection. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param permission: The permission: current supported actions are joinLeaveGroup and - sendToGroup. - :type permission: str or ~Permissions - :param connection_id: Target connection Id. - :type connection_id: str - :keyword target_name: Optional. If not set, grant the permission to all the targets. If set, - grant the permission to the specific target. The meaning of the target depends on the specific - permission. - :paramtype target_name: str - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - target_name = kwargs.pop('target_name', None) # type: Optional[str] - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'permission': _SERIALIZER.url("permission", permission, 'str'), - 'connectionId': _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if target_name is not None: - query_parameters['targetName'] = _SERIALIZER.query("target_name", target_name, 'str') - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="PUT", - url=url, - params=query_parameters, - **kwargs - ) - - -def build_revoke_permission_request( - hub, # type: str - permission, # type: Permissions - connection_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Revoke permission for the connection. - - Revoke permission for the connection. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param permission: The permission: current supported actions are joinLeaveGroup and - sendToGroup. - :type permission: str or ~Permissions - :param connection_id: Target connection Id. - :type connection_id: str - :keyword target_name: Optional. If not set, revoke the permission for all targets. If set, - revoke the permission for the specific target. The meaning of the target depends on the - specific permission. - :paramtype target_name: str - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - target_name = kwargs.pop('target_name', None) # type: Optional[str] - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'permission': _SERIALIZER.url("permission", permission, 'str'), - 'connectionId': _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if target_name is not None: - query_parameters['targetName'] = _SERIALIZER.query("target_name", target_name, 'str') - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="DELETE", - url=url, - params=query_parameters, - **kwargs - ) - - -def build_check_permission_request( - hub, # type: str - permission, # type: Permissions - connection_id, # type: str - **kwargs # type: Any -): - # type: (...) -> HttpRequest - """Check if a connection has permission to the specified action. - - Check if a connection has permission to the specified action. - - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this request builder into your code flow. - - :param hub: Target hub name, which should start with alphabetic characters and only contain - alpha-numeric characters or underscore. - :type hub: str - :param permission: The permission: current supported actions are joinLeaveGroup and - sendToGroup. - :type permission: ~Permissions - :param connection_id: Target connection Id. - :type connection_id: str - :keyword target_name: Optional. If not set, get the permission for all targets. If set, get the - permission for the specific target. The meaning of the target depends on the specific - permission. - :paramtype target_name: str - :keyword api_version: Api Version. - :paramtype api_version: str - :return: Returns an :class:`~azure.messaging.webpubsubservice.core.rest.HttpRequest` that you will pass to the client's `send_request` method. - See https://aka.ms/azsdk/python/llcwiki for how to incorporate this response into your code flow. - :rtype: ~azure.messaging.webpubsubservice.core.rest.HttpRequest - """ - target_name = kwargs.pop('target_name', None) # type: Optional[str] - api_version = kwargs.pop('api_version', "2021-05-01-preview") # type: Optional[str] - - # Construct URL - url = kwargs.pop("template_url", '/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}') - path_format_arguments = { - 'hub': _SERIALIZER.url("hub", hub, 'str', pattern=r'^[A-Za-z][A-Za-z0-9_`,.[\]]{0,127}$'), - 'permission': _SERIALIZER.url("permission", permission, 'str'), - 'connectionId': _SERIALIZER.url("connection_id", connection_id, 'str', min_length=1), - } - url = _format_url_section(url, **path_format_arguments) - - # Construct parameters - query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] - if target_name is not None: - query_parameters['targetName'] = _SERIALIZER.query("target_name", target_name, 'str') - if api_version is not None: - query_parameters['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') - - return HttpRequest( - method="HEAD", - url=url, - params=query_parameters, - **kwargs - ) diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/examples/send_messages.py b/sdk/webpubsub/azure-messaging-webpubsubservice/examples/send_messages.py deleted file mode 100644 index 96913de2dde1..000000000000 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/examples/send_messages.py +++ /dev/null @@ -1,54 +0,0 @@ -import io -import logging -import os - -from azure.messaging.webpubsubservice import WebPubSubServiceClient -from azure.messaging.webpubsubservice.rest import * - -logging.basicConfig(level=logging.DEBUG) -LOG = logging.getLogger() - -try: - connection_string = os.environ['WEBPUBSUB_CONNECTION_STRING'] -except KeyError: - LOG.error("Missing environment variable 'WEBPUBSUB_CONNECTION_STRING' - please set if before running the example") - exit() - -# Build a client from the connection string. And for this example, we have enabled debug -# tracing. For production code, this should be turned off. -client = WebPubSubServiceClient.from_connection_string(connection_string, tracing_enabled=True) - -# Send a json message to everybody on the given hub... -request = build_send_to_all_request('myHub', json={ 'Hello': 'all!' }) -print(request.headers) -response = client.send_request(request) -try: - # Raise an exception if the service rejected the call - response.raise_for_status() - print('Successfully sent a JSON message') -except: - print('Failed to send JSON message: {}'.format(response)) - - -# Send a text message to everybody on the given hub... -request = build_send_to_all_request('ahub', content='hello, text!', content_type='text/plain') -response = client.send_request(request) -try: - # Raise an exception if the service rejected the call - response.raise_for_status() - print('Successfully sent a TEXT message') -except: - print('Failed to send TEXT message: {}'.format(response)) - - - -# Send a json message from a stream to everybody on the given hub... -request = build_send_to_all_request('ahub', content=io.BytesIO(b'{ "hello": "world" }'), content_type='application/json') -response = client.send_request(request) -try: - # Raise an exception if the service rejected the call - response.raise_for_status() - print('Successfully sent a JSON message from a stream') -except: - print('Failed to send JSON message from a stream: {}'.format(response)) - diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/samples/send_messages_aad.py b/sdk/webpubsub/azure-messaging-webpubsubservice/samples/send_messages_aad.py new file mode 100644 index 000000000000..248f9d822ba8 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/samples/send_messages_aad.py @@ -0,0 +1,72 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the ""Software""), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# -------------------------------------------------------------------------- +import io +import logging +import os + +from azure.messaging.webpubsubservice import WebPubSubServiceClient +from azure.identity import DefaultAzureCredential +from azure.core.exceptions import HttpResponseError + +logging.basicConfig(level=logging.DEBUG) +LOG = logging.getLogger() + +# Set the values of the client ID, tenant ID, and client secret of the AAD application as environment variables: +# AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET, WEBPUBSUB_ENDPOINT +try: + endpoint = os.environ["WEBPUBSUB_ENDPOINT"] +except KeyError: + LOG.error("Missing environment variable 'WEBPUBSUB_ENDPOINT' - please set if before running the example") + exit() + +# Build a client through AAD +client = WebPubSubServiceClient(credential=DefaultAzureCredential(), endpoint=endpoint) + +# Send a json message to everybody on the given hub... +try: + # Raise an exception if the service rejected the call + client.send_to_all('Hub', message={'Hello': 'all'}) + print('Successfully sent a JSON message') +except HttpResponseError as e: + print('Failed to send JSON message: {}'.format(e.response.json())) + +# Send a text message to everybody on the given hub... +try: + # Raise an exception if the service rejected the call + client.send_to_all('Hub', message='hello, text!', content_type='text/plain') + print('Successfully sent a text message') +except HttpResponseError as e: + print('Failed to send text message: {}'.format(e.response.json())) + + +# Send a json message from a stream to everybody on the given hub... +try: + # Raise an exception if the service rejected the call + client.send_to_all('Hub', message=io.BytesIO(b'{ "hello": "world" }'), content_type='application/json') + print('Successfully sent a JSON message') +except HttpResponseError as e: + print('Failed to send JSON message: {}'.format(e.response.json())) diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/samples/send_messages_aad_apim_proxy.py b/sdk/webpubsub/azure-messaging-webpubsubservice/samples/send_messages_aad_apim_proxy.py new file mode 100644 index 000000000000..40fb54b6645c --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/samples/send_messages_aad_apim_proxy.py @@ -0,0 +1,75 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the ""Software""), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# -------------------------------------------------------------------------- +import io +import logging +import os + +from azure.messaging.webpubsubservice import WebPubSubServiceClient +from azure.identity import DefaultAzureCredential +from azure.core.exceptions import HttpResponseError + +logging.basicConfig(level=logging.DEBUG) +LOG = logging.getLogger() + +# Set the values of the client ID, tenant ID, and client secret of the AAD application as environment variables: +# AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET, WEBPUBSUB_ENDPOINT +try: + endpoint = os.environ["WEBPUBSUB_ENDPOINT"] + reverse_proxy_endpoint = os.environ["WEBPUBSUB_REVERSE_PROXY_ENDPOINT"] +except KeyError: + LOG.error("Missing environment variable 'WEBPUBSUB_ENDPOINT' or 'WEBPUBSUB_REVERSE_RPOXY_ENDPOINT' - please set if before running the example") + exit() + +# Build a client through AAD +# If you want to know more about the effect of `reverse_proxy_endpoint`, please reference: https://github.com/Azure/azure-webpubsub/issues/194 +client = WebPubSubServiceClient(credential=DefaultAzureCredential(), endpoint=endpoint, reverse_proxy_endpoint=reverse_proxy_endpoint) + +# Send a json message to everybody on the given hub... +try: + # Raise an exception if the service rejected the call + client.send_to_all('Hub', message={'Hello': 'reverse_proxy_endpoint!'}) + print('Successfully sent a JSON message') +except HttpResponseError as e: + print('Failed to send JSON message: {}'.format(e.response.json())) + +# Send a text message to everybody on the given hub... +try: + # Raise an exception if the service rejected the call + client.send_to_all('Hub', message='hello, reverse_proxy_endpoint!', content_type='text/plain') + print('Successfully sent a JSON message') +except HttpResponseError as e: + print('Failed to send JSON message: {}'.format(e.response.json())) + + +# Send a json message from a stream to everybody on the given hub... +try: + # Raise an exception if the service rejected the call + client.send_to_all('Hub', message=io.BytesIO(b'{ "hello": "reverse_proxy_endpoint" }'), content_type='application/json') + print('Successfully sent a JSON message') +except HttpResponseError as e: + print('Failed to send JSON message: {}'.format(e.response.json())) + diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/samples/send_messages_connection_string.py b/sdk/webpubsub/azure-messaging-webpubsubservice/samples/send_messages_connection_string.py new file mode 100644 index 000000000000..f39b1f182fa5 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/samples/send_messages_connection_string.py @@ -0,0 +1,70 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the ""Software""), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# -------------------------------------------------------------------------- +import io +import logging +import os + +from azure.messaging.webpubsubservice import WebPubSubServiceClient +from azure.core.exceptions import HttpResponseError + +logging.basicConfig(level=logging.DEBUG) +LOG = logging.getLogger() + +try: + connection_string = os.environ['WEBPUBSUB_CONNECTION_STRING'] +except KeyError: + LOG.error("Missing environment variable 'WEBPUBSUB_CONNECTION_STRING' - please set if before running the example") + exit() + +# Build a client from the connection string. And for this example, we have enabled debug +# tracing. For production code, this should be turned off. +client = WebPubSubServiceClient.from_connection_string(connection_string, logging_enable=True) + +try: + # Raise an exception if the service rejected the call + client.send_to_all('Hub', message={'Hello': 'all!'}) + print('Successfully sent a JSON message') +except HttpResponseError as e: + print('Failed to send JSON message: {}'.format(e.response.json())) + +# Send a text message to everybody on the given hub... +try: + # Raise an exception if the service rejected the call + client.send_to_all('Hub', message='hello, text!', content_type='text/plain') + print('Successfully sent a JSON message') +except HttpResponseError as e: + print('Failed to send JSON message: {}'.format(e.response.json())) + + +# Send a json message from a stream to everybody on the given hub... +try: + # Raise an exception if the service rejected the call + client.send_to_all('Hub', message=io.BytesIO(b'{ "hello": "world" }'), content_type='application/json') + print('Successfully sent a JSON message') +except HttpResponseError as e: + print('Failed to send JSON message: {}'.format(e.response.json())) + diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/samples/send_messages_connection_string_apim_proxy.py b/sdk/webpubsub/azure-messaging-webpubsubservice/samples/send_messages_connection_string_apim_proxy.py new file mode 100644 index 000000000000..887ca39329d7 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/samples/send_messages_connection_string_apim_proxy.py @@ -0,0 +1,72 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the ""Software""), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# -------------------------------------------------------------------------- +import io +import logging +import os + +from azure.messaging.webpubsubservice import WebPubSubServiceClient +from azure.core.exceptions import HttpResponseError + +logging.basicConfig(level=logging.DEBUG) +LOG = logging.getLogger() + +try: + connection_string = os.environ['WEBPUBSUB_CONNECTION_STRING'] + reverse_proxy_endpoint = os.environ["WEBPUBSUB_REVERSE_RPOXY_ENDPOINT"] +except KeyError: + LOG.error("Missing environment variable 'WEBPUBSUB_CONNECTION_STRING' or 'WEBPUBSUB_REVERSE_RPOXY_ENDPOINT' - please set if before running the example") + exit() + +# Build a client from the connection string. And for this example, we have enabled debug +# tracing. For production code, this should be turned off. +# If you want to know more about the effect of `reverse_proxy_endpoint`, please reference: https://github.com/Azure/azure-webpubsub/issues/194 +client = WebPubSubServiceClient.from_connection_string(connection_string, logging_enable=True, reverse_proxy_endpoint=reverse_proxy_endpoint) + +try: + # Raise an exception if the service rejected the call + client.send_to_all('Hub', message={'Hello': 'connection_string_reverse_proxy!'}) + print('Successfully sent a JSON message') +except HttpResponseError as e: + print('Failed to send JSON message: {}'.format(e.response.json())) + +# Send a text message to everybody on the given hub... +try: + # Raise an exception if the service rejected the call + client.send_to_all('Hub', message='hello, connection_string_reverse_proxy!', content_type='text/plain') + print('Successfully sent a JSON message') +except HttpResponseError as e: + print('Failed to send JSON message: {}'.format(e.response.json())) + + +# Send a json message from a stream to everybody on the given hub... +try: + # Raise an exception if the service rejected the call + client.send_to_all('Hub', message=io.BytesIO(b'{ "hello": "connection_string_reverse_proxy" }'), content_type='application/json') + print('Successfully sent a JSON message') +except HttpResponseError as e: + print('Failed to send JSON message: {}'.format(e.response.json())) + diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/setup.py b/sdk/webpubsub/azure-messaging-webpubsubservice/setup.py index f5403c2290e5..839894ced78a 100644 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/setup.py +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/setup.py @@ -61,9 +61,9 @@ ] ), install_requires=[ - "azure-core<2.0.0,>=1.10.0", - "msrest>=0.6.18", - "cryptography>=2.1.4", + "azure-core<2.0.0,>=1.18.0", + "msrest>=0.6.21", + "cryptography>=2.8.0", "pyjwt>=1.7.1", "six>=1.12.0", ], diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/swagger/README.md b/sdk/webpubsub/azure-messaging-webpubsubservice/swagger/README.md new file mode 100644 index 000000000000..34e185dad628 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/swagger/README.md @@ -0,0 +1,62 @@ +# Azure Purview for Python + +> see https://aka.ms/autorest + +### Setup + +Install Autorest v3 + +```ps +npm install -g autorest +``` + +### Generation + +```ps +cd +autorest +``` + +### Settings + +```yaml +input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/webpubsub/data-plane/WebPubSub/preview/2021-08-01-preview/webpubsub.json +output-folder: ../azure/messaging/webpubsubservice +namespace: azure.messaging.webpubsubservice +package-name: azure-messaging-webpubsubservice +license-header: MICROSOFT_MIT_NO_VERSION +clear-output-folder: true +no-namespace-folders: true +python: true +title: WebPubSubServiceClient +version-tolerant: true +package-version: 1.0.0b2 +add-credential: true +credential-scopes: https://webpubsub.azure.com/.default +``` + + +Here's the directive to delete the health api operation that we don't need / want +```yaml + +directive: + - from: swagger-document + where: $["paths"]["/api/health"] + transform: > + delete $["head"]; +``` + +Here's the directive to move the operations from the webpubsub operation group directly onto the client + +```yaml + +directive: + - from: swagger-document + where: $["paths"][*] + transform: > + for (var op of Object.values($)) { + if (op["operationId"].includes("WebPubSub_")) { + op["operationId"] = op["operationId"].replace("WebPubSub_", ""); + } + } +``` \ No newline at end of file diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/tests/conftest.py b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/conftest.py new file mode 100644 index 000000000000..a6ab83f7f5f0 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/conftest.py @@ -0,0 +1,15 @@ +# 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. +# -------------------------------------------------------------------------- + +import sys + +# fixture needs to be visible from conftest + +# Ignore async tests for Python < 3.5 +collect_ignore_glob = [] +if sys.version_info < (3, 5): + collect_ignore_glob.append("*_async.py") \ No newline at end of file diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke.test_webpubsub_send_request.yaml b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke.test_webpubsub_send_request.yaml new file mode 100644 index 000000000000..3209b9003870 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke.test_webpubsub_send_request.yaml @@ -0,0 +1,34 @@ +interactions: +- request: + body: test_webpubsub_send_request + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '27' + Content-Type: + - text/plain + User-Agent: + - azsdk-python-messaging-webpubsubservice/1.0.0b2 Python/3.7.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://myservice.webpubsub.azure.com/api/hubs/Hub/:send?api-version=2021-08-01-preview + response: + body: + string: '' + headers: + connection: + - keep-alive + content-length: + - '0' + date: + - Fri, 17 Sep 2021 02:21:35 GMT + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 202 + message: Accepted +version: 1 diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke.test_webpubsub_send_to_all.yaml b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke.test_webpubsub_send_to_all.yaml new file mode 100644 index 000000000000..3e374b336a17 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke.test_webpubsub_send_to_all.yaml @@ -0,0 +1,34 @@ +interactions: +- request: + body: '{"hello": "test_webpubsub_send_to_all"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '39' + Content-Type: + - text/plain + User-Agent: + - azsdk-python-messaging-webpubsubservice/1.0.0b2 Python/3.7.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://myservice.webpubsub.azure.com/api/hubs/Hub/:send?api-version=2021-08-01-preview + response: + body: + string: '' + headers: + connection: + - keep-alive + content-length: + - '0' + date: + - Fri, 17 Sep 2021 02:21:37 GMT + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 202 + message: Accepted +version: 1 diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke.test_webpubsub_send_to_all_api_management_proxy.yaml b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke.test_webpubsub_send_to_all_api_management_proxy.yaml new file mode 100644 index 000000000000..2be7cda87237 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke.test_webpubsub_send_to_all_api_management_proxy.yaml @@ -0,0 +1,32 @@ +interactions: +- request: + body: '{"hello": "test_webpubsub_send_to_all_api_management_proxy"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '60' + Content-Type: + - text/plain + User-Agent: + - azsdk-python-messaging-webpubsubservice/1.0.0b2 Python/3.7.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://myservice.azure-api.net/api/hubs/Hub/:send?api-version=2021-08-01-preview + response: + body: + string: '' + headers: + content-length: + - '0' + date: + - Wed, 22 Sep 2021 07:54:54 GMT + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 202 + message: Accepted +version: 1 diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke_async.test_webpubsub_send_to_all.yaml b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke_async.test_webpubsub_send_to_all.yaml new file mode 100644 index 000000000000..e8ce7e871950 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke_async.test_webpubsub_send_to_all.yaml @@ -0,0 +1,25 @@ +interactions: +- request: + body: '{"hello": "test_webpubsub_send_to_all"}' + headers: + Content-Length: + - '39' + Content-Type: + - text/plain + User-Agent: + - azsdk-python-messaging-webpubsubservice/1.0.0b2 Python/3.7.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://myservice.webpubsub.azure.com/api/hubs/Hub/:send?api-version=2021-08-01-preview + response: + body: + string: '' + headers: + connection: keep-alive + content-length: '0' + date: Fri, 17 Sep 2021 02:23:19 GMT + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 202 + message: Accepted + url: https://webpubsub-yyc.webpubsub.azure.com/api/hubs/Hub/:send?api-version=2021-08-01-preview +version: 1 diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke_async.test_webpubsub_send_to_all_apim_proxy.yaml b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke_async.test_webpubsub_send_to_all_apim_proxy.yaml new file mode 100644 index 000000000000..6a03ef2584c6 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/recordings/test_smoke_async.test_webpubsub_send_to_all_apim_proxy.yaml @@ -0,0 +1,24 @@ +interactions: +- request: + body: '{"hello": "test_webpubsub_send_to_all_apim_proxy"}' + headers: + Content-Length: + - '50' + Content-Type: + - text/plain + User-Agent: + - azsdk-python-messaging-webpubsubservice/1.0.0b2 Python/3.7.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://myservice.azure-api.net/api/hubs/Hub/:send?api-version=2021-08-01-preview + response: + body: + string: '' + headers: + content-length: '0' + date: Fri, 17 Sep 2021 02:23:21 GMT + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 202 + message: Accepted + url: https://apimanagement-yyc.azure-api.net/api/hubs/Hub/:send?api-version=2021-08-01-preview +version: 1 diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/tests/test_send_requests.py b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/test_send_requests.py deleted file mode 100644 index 4f402e2e719b..000000000000 --- a/sdk/webpubsub/azure-messaging-webpubsubservice/tests/test_send_requests.py +++ /dev/null @@ -1,38 +0,0 @@ -import io - -from azure.messaging.webpubsubservice import WebPubSubServiceClient -from azure.messaging.webpubsubservice.rest import * - -from azure.core.credentials import AzureKeyCredential - -def test_build_text_request(): - request = build_send_to_all_request('hub', content='hello world', content_type='text/plain') - - assert request.headers['content-type'] == 'text/plain' - assert request.content == 'hello world' - -def test_build_json_request(): - client = WebPubSubServiceClient('https://www.microsoft.com/api', AzureKeyCredential('abcd')) - request = build_send_to_all_request('hub', json={'hello': 'world'}) - assert request.headers['content-type'] == 'application/json' - -def test_build_stream_request(): - stream = io.BytesIO(b'1234') - client = WebPubSubServiceClient('https://www.microsoft.com/api', AzureKeyCredential('abcd')) - request = build_send_to_all_request('hub', content=stream, content_type='application/octet-stream') - assert request.headers['content-type'] == 'application/octet-stream' - -def test_build_stream_json_request(): - stream = io.BytesIO(b'{ "hello": "web" }') - client = WebPubSubServiceClient('https://www.microsoft.com/api', AzureKeyCredential('abcd')) - request = build_send_to_all_request('hub', content=stream, content_type='application/octet-json') - assert request.headers['content-type'] == 'application/octet-json' - -def test_build_send_message_exclude(): - stream = io.BytesIO(b'{ "hello": "web" }') - client = WebPubSubServiceClient('https://www.microsoft.com/api', AzureKeyCredential('abcd')) - request = build_send_to_all_request('hub', content=stream, content_type='application/octet-json', excluded=['a', 'b', 'c']) - assert 'excluded=a&' in request.url - assert 'excluded=b&' in request.url - assert 'excluded=c' in request.url - assert 'excluded=d' not in request.url diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/tests/test_smoke.py b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/test_smoke.py new file mode 100644 index 000000000000..7a1672964c05 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/test_smoke.py @@ -0,0 +1,36 @@ +# coding: utf-8 +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# ------------------------------------------------------------------------- +import pytest +from testcase import WebpubsubTest, WebpubsubPowerShellPreparer +from azure.messaging.webpubsubservice.operations._operations import build_send_to_all_request +from azure.core.exceptions import ServiceRequestError + +class WebpubsubSmokeTest(WebpubsubTest): + + + @WebpubsubPowerShellPreparer() + def test_webpubsub_send_to_all(self, webpubsub_endpoint): + client = self.create_client(endpoint=webpubsub_endpoint) + client.send_to_all('Hub', {'hello': 'test_webpubsub_send_to_all'}) + + @WebpubsubPowerShellPreparer() + def test_webpubsub_send_to_all_api_management_proxy(self, webpubsub_endpoint, webpubsub_reverse_proxy_endpoint=None): + client = self.create_client(endpoint=webpubsub_endpoint, reverse_proxy_endpoint=webpubsub_reverse_proxy_endpoint) + client.send_to_all('Hub', {'hello': 'test_webpubsub_send_to_all_api_management_proxy'}) + + @WebpubsubPowerShellPreparer() + def test_webpubsub_send_request(self, webpubsub_endpoint): + client = self.create_client(endpoint=webpubsub_endpoint) + request = build_send_to_all_request('Hub', content='test_webpubsub_send_request', content_type='text/plain') + response = client.send_request(request) + assert response.status_code == 202 + + @WebpubsubPowerShellPreparer() + def test_webpubsub_send_to_all_api_management_proxy_counter_test(self, webpubsub_endpoint): + client = self.create_client(endpoint=webpubsub_endpoint, reverse_proxy_endpoint='https://example.azure-api.net') + with pytest.raises(ServiceRequestError): + client.send_to_all('Hub', {'hello': 'test_webpubsub_send_to_all_api_management_proxy_counter_test'}) \ No newline at end of file diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/tests/test_smoke_async.py b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/test_smoke_async.py new file mode 100644 index 000000000000..61544d89294a --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/test_smoke_async.py @@ -0,0 +1,21 @@ +# 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. +# ------------------------------------------------------------------------- +from testcase import WebpubsubPowerShellPreparer +from testcase_async import WebpubsubTestAsync + + +class WebpubsubSmokeTestAsync(WebpubsubTestAsync): + + @WebpubsubPowerShellPreparer() + async def test_webpubsub_send_to_all(self, webpubsub_endpoint): + client = self.create_client(endpoint=webpubsub_endpoint) + await client.send_to_all('Hub', {'hello': 'test_webpubsub_send_to_all'}) + + @WebpubsubPowerShellPreparer() + async def test_webpubsub_send_to_all_apim_proxy(self, webpubsub_endpoint, webpubsub_reverse_proxy_endpoint=None): + client = self.create_client(endpoint=webpubsub_endpoint, reverse_proxy_endpoint=webpubsub_reverse_proxy_endpoint) + await client.send_to_all('Hub', {'hello': 'test_webpubsub_send_to_all_apim_proxy'}) \ No newline at end of file diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/tests/testcase.py b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/testcase.py new file mode 100644 index 000000000000..9f2875e70fc4 --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/testcase.py @@ -0,0 +1,31 @@ +# coding: utf-8 +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- +import functools +from devtools_testutils import AzureTestCase, PowerShellPreparer +from azure.messaging.webpubsubservice import WebPubSubServiceClient + + +class WebpubsubTest(AzureTestCase): + def __init__(self, method_name, **kwargs): + super(WebpubsubTest, self).__init__(method_name, **kwargs) + + def create_client(self, endpoint, reverse_proxy_endpoint=None): + credential = self.get_credential(WebPubSubServiceClient) + return self.create_client_from_credential( + WebPubSubServiceClient, + credential=credential, + endpoint=endpoint, + reverse_proxy_endpoint=reverse_proxy_endpoint + ) + + +WebpubsubPowerShellPreparer = functools.partial( + PowerShellPreparer, + "webpubsub", + webpubsub_endpoint="https://myservice.webpubsub.azure.com", + webpubsub_reverse_proxy_endpoint="https://myservice.azure-api.net" +) diff --git a/sdk/webpubsub/azure-messaging-webpubsubservice/tests/testcase_async.py b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/testcase_async.py new file mode 100644 index 000000000000..46f9f1662b8e --- /dev/null +++ b/sdk/webpubsub/azure-messaging-webpubsubservice/tests/testcase_async.py @@ -0,0 +1,22 @@ +# 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. +# -------------------------------------------------------------------------- +from devtools_testutils import AzureTestCase +from azure.messaging.webpubsubservice.aio import WebPubSubServiceClient + + +class WebpubsubTestAsync(AzureTestCase): + def __init__(self, method_name, **kwargs): + super(WebpubsubTestAsync, self).__init__(method_name, **kwargs) + + def create_client(self, endpoint, reverse_proxy_endpoint=None): + credential = self.get_credential(WebPubSubServiceClient, is_async=True) + return self.create_client_from_credential( + WebPubSubServiceClient, + credential=credential, + endpoint=endpoint, + reverse_proxy_endpoint=reverse_proxy_endpoint + ) diff --git a/shared_requirements.txt b/shared_requirements.txt index 9e2f21db00c4..5c61dc91ca05 100644 --- a/shared_requirements.txt +++ b/shared_requirements.txt @@ -219,10 +219,11 @@ opentelemetry-sdk<2.0.0,>=1.0.0 #override azure-core-tracing-opentelemetry opentelemetry-api<2.0.0,>=1.0.0 #override azure-identity six>=1.12.0 #override azure-keyvault-keys six>=1.12.0 -#override azure-messaging-webpubsubservice azure-core<2.0.0,>=1.10.0 -#override azure-messaging-webpubsubservice msrest>=0.6.18 +#override azure-messaging-webpubsubservice azure-core<2.0.0,>=1.18.0 +#override azure-messaging-webpubsubservice msrest>=0.6.21 #override azure-messaging-webpubsubservice pyjwt>=1.7.1 #override azure-messaging-webpubsubservice six>=1.12.0 +#override azure-messaging-webpubsubservice cryptography>=2.8.0 #override azure-mixedreality-authentication azure-core<2.0.0,>=1.4.0 #override azure-iot-deviceupdate azure-core<2.0.0,>=1.6.0 #override azure-mgmt-changeanalysis msrest>=0.6.21