From 3fa62e79ff883af5a7704ee27be9af9bf538094f Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Mon, 12 Feb 2024 17:57:26 -0800 Subject: [PATCH 01/24] wip --- .../_azure_appconfiguration_client.py | 85 +++++++++++++++--- ...tor_configuration_settings_by_page_etag.py | 90 +++++++++++++++++++ 2 files changed, 164 insertions(+), 11 deletions(-) create mode 100644 sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py index f45b6acc9a05..bf40117f6d70 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py @@ -114,15 +114,18 @@ def from_connection_string(cls, connection_string: str, **kwargs: Any) -> "Azure def list_configuration_settings( self, *, + page_etags: Optional[List[str]] = None, key_filter: Optional[str] = None, label_filter: Optional[str] = None, accept_datetime: Optional[Union[datetime, str]] = None, fields: Optional[List[str]] = None, **kwargs: Any, - ) -> ItemPaged[ConfigurationSetting]: + ) -> Union[ItemPaged[ConfigurationSetting], List[Optional[ConfigurationSetting]]]: """List the configuration settings stored in the configuration service, optionally filtered by key, label and accept_datetime. + :keyword page_etags: the page etags to compare with the targeted resource's etag. + :paramtype page_etags: list[str] or None :keyword key_filter: filter results based on their keys. '*' can be used as wildcard in the beginning or end of the filter :paramtype key_filter: str or None @@ -172,7 +175,9 @@ def list_configuration_settings( """ @distributed_trace - def list_configuration_settings(self, *args, **kwargs) -> ItemPaged[ConfigurationSetting]: + def list_configuration_settings( + self, *args, **kwargs + ) -> Union[ItemPaged[ConfigurationSetting], List[Optional[ItemPaged[ConfigurationSetting]]]]: accept_datetime = kwargs.pop("accept_datetime", None) if isinstance(accept_datetime, datetime): accept_datetime = str(accept_datetime) @@ -180,6 +185,7 @@ def list_configuration_settings(self, *args, **kwargs) -> ItemPaged[Configuratio if select: select = ["locked" if x == "read_only" else x for x in select] snapshot_name = kwargs.pop("snapshot_name", None) + page_etags = kwargs.pop("page_etags", None) try: if snapshot_name is not None: @@ -190,19 +196,76 @@ def list_configuration_settings(self, *args, **kwargs) -> ItemPaged[Configuratio cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs], **kwargs, ) + key_filter, kwargs = get_key_filter(*args, **kwargs) label_filter, kwargs = get_label_filter(*args, **kwargs) - return self._impl.get_key_values( # type: ignore - key=key_filter, - label=label_filter, - accept_datetime=accept_datetime, - select=select, - cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs], - **kwargs, - ) + + if page_etags is None: + return self._impl.get_key_values( # type: ignore + key=key_filter, + label=label_filter, + accept_datetime=accept_datetime, + select=select, + cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), + **kwargs, + ) + + result = [] + continuation_token = None + for page_etag in page_etags: + try: + response = self._impl.get_key_values( # type: ignore + key=key_filter, + label=label_filter, + accept_datetime=accept_datetime, + select=select, + if_none_match=page_etag, + cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), + **kwargs, + ).by_page(continuation_token = continuation_token) + response.next() + result.append(response._current_page) + continuation_token = response.continuation_token + except ResourceNotModifiedError as e: + result.append(None) + continuation_token = e.response.headers['Link'][1:e.response.headers['Link'].index(">")] + + return result except binascii.Error as exc: raise binascii.Error("Connection string secret has incorrect padding") from exc - + + # @distributed_trace + # def monitor_single_page_configuration_settings( + # self, + # *, + # page_etag: str, + # continuation_token: Optional[str], + # key_filter: Optional[str] = None, + # label_filter: Optional[str] = None, + # accept_datetime: Optional[Union[datetime, str]] = None, + # fields: Optional[List[str]] = None, + # **kwargs: Any, + # ) -> Optional[ItemPaged[ConfigurationSetting]]: + # breakpoint() + # if fields: + # fields = ["locked" if x == "read_only" else x for x in fields] + # try: + # response = self._impl.get_key_values( # type: ignore + # key=key_filter, + # label=label_filter, + # accept_datetime=accept_datetime, + # select=fields, + # if_none_match=page_etag, + # cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), + # **kwargs, + # ).by_page(continuation_token = continuation_token) + # response.next() + # return response._current_page + # except ResourceNotModifiedError as e: + # print("No changes") + # pass + # return None + @distributed_trace def get_configuration_setting( self, diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py new file mode 100644 index 000000000000..94ac0f28b7ea --- /dev/null +++ b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py @@ -0,0 +1,90 @@ +import os +from uuid import uuid4 +from azure.appconfiguration import AzureAppConfigurationClient, ConfigurationSetting +from azure.core.exceptions import ResourceExistsError +from dotenv import find_dotenv, load_dotenv + + +def main(): + load_dotenv(find_dotenv()) + CONNECTION_STRING = os.environ["APPCONFIGURATION_CONNECTION_STRING"] + + client = AzureAppConfigurationClient.from_connection_string(CONNECTION_STRING) + + # prepare 400 configuration settings + for i in range(400): + client.add_configuration_setting( + ConfigurationSetting( + key="sample_key_" + str(i), + label="sample_label_" + str(i), + ) + ) + # there will have 4 pages in list result, there are 100 configuration settings per page. + + # print page etags + print("**********************print page etags*****************************") + page_etags = [] + items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") + iterator = items.by_page() # azure.core.paging.PageIterator obj + for page in iterator: + etag = iterator._response.http_response.headers['Etag'] + page_etags.append(etag) + print(f"ETag: {etag}") + + # monitor page updates + print("**********************monitor page updates*****************************") + response = client.list_configuration_settings(page_etags=page_etags, key_filter="sample_key_*", label_filter="sample_label_*") + for page in response: + if page: + for item in page: + print(f"Key: {item.key}, Label: {item.label}") + else: + print(page) + # expected output: [None, None, None, None, None] + + # add a configuration setting + client.add_configuration_setting( + ConfigurationSetting( + key="sample_key_201", + label="sample_label_202", + ) + ) + # there will have 5 pages in list result, first 4 pages with 100 items and the last page with one item + + # print page etags after updates + print("*****************print page etags after updates**********************************") + items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") + iterator = items.by_page() # azure.core.paging.PageIterator obj + for page in iterator: + etag = iterator._response.http_response.headers['Etag'] + print(f"ETag: {etag}") + + # monitor page updates + print("**********************monitor page updates*****************************") + response = client.list_configuration_settings(page_etags=page_etags, key_filter="sample_key_*", label_filter="sample_label_*") + for page in response: + if page: + for item in page: + print(f"Key: {item.key}, Label: {item.label}") + else: + print(page) + # expected output: [, , , , ] + + # for page_etag, continuation_token in zip(page_etags, continuation_tokens): + # result = client.monitor_single_page_configuration_settings(page_etag=page_etag, continuation_token=continuation_token, key_filter="sample_key_*", label_filter="sample_label_*") + # if result: + # for configuration_setting in result: + # print(f"Key: {configuration_setting.key}, Label: {configuration_setting.label}") + # print(result) + + # clean up + print("*************************clean up**************************") + count = 0 + for item in client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*"): + client.delete_configuration_setting(item.key, label=item.label) + count += 1 + print(count) + + +if __name__ == "__main__": + main() \ No newline at end of file From ea2628f36eecb876860de81aa2eb22103b48a4c3 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 15 Feb 2024 12:15:11 -0800 Subject: [PATCH 02/24] Change to loop by continuation_token instead of etag --- .../_azure_appconfiguration_client.py | 60 ++++++++----------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py index bf40117f6d70..3839f74438b6 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py @@ -212,14 +212,34 @@ def list_configuration_settings( result = [] continuation_token = None - for page_etag in page_etags: + index = 0 + try: + response = self._impl.get_key_values( # type: ignore + key=key_filter, + label=label_filter, + accept_datetime=accept_datetime, + select=select, + if_none_match=page_etags[index], + cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), + **kwargs, + ).by_page() + response.next() + result.append(response._current_page) + continuation_token = response.continuation_token + except ResourceNotModifiedError as e: + result.append(None) + link = e.response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 + + while continuation_token: try: response = self._impl.get_key_values( # type: ignore key=key_filter, label=label_filter, accept_datetime=accept_datetime, select=select, - if_none_match=page_etag, + if_none_match=page_etags[index] if index < len(page_etags) else None, cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), **kwargs, ).by_page(continuation_token = continuation_token) @@ -228,44 +248,14 @@ def list_configuration_settings( continuation_token = response.continuation_token except ResourceNotModifiedError as e: result.append(None) - continuation_token = e.response.headers['Link'][1:e.response.headers['Link'].index(">")] + link = e.response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 return result except binascii.Error as exc: raise binascii.Error("Connection string secret has incorrect padding") from exc - # @distributed_trace - # def monitor_single_page_configuration_settings( - # self, - # *, - # page_etag: str, - # continuation_token: Optional[str], - # key_filter: Optional[str] = None, - # label_filter: Optional[str] = None, - # accept_datetime: Optional[Union[datetime, str]] = None, - # fields: Optional[List[str]] = None, - # **kwargs: Any, - # ) -> Optional[ItemPaged[ConfigurationSetting]]: - # breakpoint() - # if fields: - # fields = ["locked" if x == "read_only" else x for x in fields] - # try: - # response = self._impl.get_key_values( # type: ignore - # key=key_filter, - # label=label_filter, - # accept_datetime=accept_datetime, - # select=fields, - # if_none_match=page_etag, - # cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), - # **kwargs, - # ).by_page(continuation_token = continuation_token) - # response.next() - # return response._current_page - # except ResourceNotModifiedError as e: - # print("No changes") - # pass - # return None - @distributed_trace def get_configuration_setting( self, From 76286d4afe8e2770a9a6d7ea026566137df75e28 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 15 Feb 2024 12:15:48 -0800 Subject: [PATCH 03/24] Patch request header --- .../_generated/operations/_patch.py | 170 +++++++++++++++++- 1 file changed, 168 insertions(+), 2 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py index f7dd32510333..68b442ca50a0 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py @@ -6,9 +6,175 @@ Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ -from typing import List +from typing import Any, Iterable, List, Optional, Union +import urllib.parse -__all__: List[str] = [] # Add all objects you want publicly available to users at this package level +from azure.core.exceptions import ( + ClientAuthenticationError, + HttpResponseError, + ResourceExistsError, + ResourceNotFoundError, + ResourceNotModifiedError, + map_error, +) +from azure.core.paging import ItemPaged +from azure.core.pipeline import PipelineResponse +from azure.core.rest import HttpRequest +from azure.core.tracing.decorator import distributed_trace +from azure.core.utils import case_insensitive_dict + +from ._azure_app_configuration_operations import ( + AzureAppConfigurationOperationsMixin as GeneratedAzureAppConfigOps, + build_get_key_values_request, + ClsType, + _SERIALIZER, +) +from .. import models as _models +from .._vendor import _convert_request + + +class AzureAppConfigurationOperationsMixin(GeneratedAzureAppConfigOps): # pylint: disable=too-many-public-methods + @distributed_trace + def get_key_values( + self, + key: Optional[str] = None, + label: Optional[str] = None, + after: Optional[str] = None, + accept_datetime: Optional[str] = None, + select: Optional[List[Union[str, _models.KeyValueFields]]] = None, + snapshot: Optional[str] = None, + if_match: Optional[str] = None, + if_none_match: Optional[str] = None, + **kwargs: Any + ) -> Iterable["_models.KeyValue"]: + """Gets a list of key-values. + + Gets a list of key-values. + + :param key: A filter used to match keys. Default value is None. + :type key: str + :param label: A filter used to match labels. Default value is None. + :type label: str + :param after: Instructs the server to return elements that appear after the element referred to + by the specified token. Default value is None. + :type after: str + :param accept_datetime: Requests the server to respond with the state of the resource at the + specified time. Default value is None. + :type accept_datetime: str + :param select: Used to select what fields are present in the returned resource(s). Default + value is None. + :type select: list[str or ~azure.appconfiguration.models.KeyValueFields] + :param snapshot: A filter used get key-values for a snapshot. The value should be the name of + the snapshot. Not valid when used with 'key' and 'label' filters. Default value is None. + :type snapshot: str + :param if_match: Used to perform an operation only if the targeted resource's etag matches the + value provided. Default value is None. + :type if_match: str + :param if_none_match: Used to perform an operation only if the targeted resource's etag does + not match the value provided. Default value is None. + :type if_none_match: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: An iterator like instance of either KeyValue or the result of cls(response) + :rtype: ~azure.core.paging.ItemPaged[~azure.appconfiguration.models.KeyValue] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version)) + cls: ClsType[_models.KeyValueListResult] = kwargs.pop("cls", None) + + error_map = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_get_key_values_request( + key=key, + label=label, + after=after, + accept_datetime=accept_datetime, + select=select, + snapshot=snapshot, + if_match=if_match, + if_none_match=if_none_match, + sync_token=self._config.sync_token, + api_version=api_version, + headers=_headers, + params=_params, + ) + _request = _convert_request(_request) + 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) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + + _next_request_params["api-version"] = self._config.api_version + + # Construct headers + if if_match is not None: + _headers["If-Match"] = _SERIALIZER.header("if_match", if_match, "str") + if if_none_match is not None: + _headers["If-None-Match"] = _SERIALIZER.header("if_none_match", if_none_match, "str") + _request = HttpRequest( + "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params, headers=_headers + ) + _request = _convert_request(_request) + 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) + _request.method = "GET" + return _request + + def extract_data(pipeline_response): + deserialized = self._deserialize("KeyValueListResult", pipeline_response) + list_of_elem = deserialized.items + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.next_link or None, iter(list_of_elem) + + def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + 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) + error = self._deserialize.failsafe_deserialize(_models.Error, pipeline_response) + raise HttpResponseError(response=response, model=error) + + return pipeline_response + + return ItemPaged(get_next, extract_data) + +__all__: List[str] = [ + "AzureAppConfigurationOperationsMixin", +] # Add all objects you want publicly available to users at this package level def patch_sdk(): From 9b93576e61af01470597940218fac0591d69e4a5 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 15 Feb 2024 12:16:30 -0800 Subject: [PATCH 04/24] Update sample --- ...tor_configuration_settings_by_page_etag.py | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py index 94ac0f28b7ea..56dbd0ba7c4e 100644 --- a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py +++ b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py @@ -1,7 +1,5 @@ import os -from uuid import uuid4 from azure.appconfiguration import AzureAppConfigurationClient, ConfigurationSetting -from azure.core.exceptions import ResourceExistsError from dotenv import find_dotenv, load_dotenv @@ -15,46 +13,52 @@ def main(): for i in range(400): client.add_configuration_setting( ConfigurationSetting( - key="sample_key_" + str(i), - label="sample_label_" + str(i), + key=f"sample_key_{str(i)}", + label=f"sample_label_{str(i)}", ) ) - # there will have 4 pages in list result, there are 100 configuration settings per page. + # there will have 4 pages while listing, there are 100 configuration settings per page. - # print page etags - print("**********************print page etags*****************************") + # get page etags + print("**********************get page etags*****************************") page_etags = [] items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") - iterator = items.by_page() # azure.core.paging.PageIterator obj + iterator = items.by_page() for page in iterator: etag = iterator._response.http_response.headers['Etag'] page_etags.append(etag) print(f"ETag: {etag}") + # ETag: "P3Oae4jiSypN6U1OApprRj2k7548_x3IYkn6NHp-wAU" next_link: /kv?key=sample_key_*&label=sample_label_*&api-version=2023-10-01&after=c2FtcGxlX2tleV8xODgKc2FtcGxlX2xhYmVsXzE4OA%3D%3D + # ETag: "x1HUZXjADggqDwAZfSArFfFgZKhLz439uDIpNY80hqc" next_link: /kv?key=sample_key_*&label=sample_label_*&api-version=2023-10-01&after=c2FtcGxlX2tleV8yNzQKc2FtcGxlX2xhYmVsXzI3NA%3D%3D + # ETag: "B37CWEtuQhXSOWv2f1T0QBlEMGFUbC1W0UVkKvSAWMM" next_link: /kv?key=sample_key_*&label=sample_label_*&api-version=2023-10-01&after=c2FtcGxlX2tleV8zNjQKc2FtcGxlX2xhYmVsXzM2NA%3D%3D + # ETag: "X-rxvugJpqrNoZwapRGx5oHI0wDnQRPiBo_MdWXZzoc" next_link: /kv?key=sample_key_*&label=sample_label_*&api-version=2023-10-01&after=c2FtcGxlX2tleV85NQpzYW1wbGVfbGFiZWxfOTU%3D + # ETag: "GoIDT8F8w0Jko6tIF3FgZz5hrPQgCN-WLTxiwK71vhw" next_link: None + # monitor page updates - print("**********************monitor page updates*****************************") + print("**********************monitor page before updates*****************************") response = client.list_configuration_settings(page_etags=page_etags, key_filter="sample_key_*", label_filter="sample_label_*") for page in response: if page: + print("This page has changes.") for item in page: print(f"Key: {item.key}, Label: {item.label}") else: - print(page) - # expected output: [None, None, None, None, None] + print("No change found.") # add a configuration setting + print("**********************add a configuration setting*****************************") client.add_configuration_setting( ConfigurationSetting( - key="sample_key_201", - label="sample_label_202", + key="sample_key_401", + label="sample_label_402", ) ) - # there will have 5 pages in list result, first 4 pages with 100 items and the last page with one item # print page etags after updates print("*****************print page etags after updates**********************************") items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") - iterator = items.by_page() # azure.core.paging.PageIterator obj + iterator = items.by_page() for page in iterator: etag = iterator._response.http_response.headers['Etag'] print(f"ETag: {etag}") @@ -62,20 +66,14 @@ def main(): # monitor page updates print("**********************monitor page updates*****************************") response = client.list_configuration_settings(page_etags=page_etags, key_filter="sample_key_*", label_filter="sample_label_*") + # List[ItemPages[ConfigurationSetting]] for page in response: if page: + print("This page has changes.") for item in page: print(f"Key: {item.key}, Label: {item.label}") else: - print(page) - # expected output: [, , , , ] - - # for page_etag, continuation_token in zip(page_etags, continuation_tokens): - # result = client.monitor_single_page_configuration_settings(page_etag=page_etag, continuation_token=continuation_token, key_filter="sample_key_*", label_filter="sample_label_*") - # if result: - # for configuration_setting in result: - # print(f"Key: {configuration_setting.key}, Label: {configuration_setting.label}") - # print(result) + print("No change found.") # clean up print("*************************clean up**************************") @@ -84,7 +82,10 @@ def main(): client.delete_configuration_setting(item.key, label=item.label) count += 1 print(count) + + items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") + print(items is None) if __name__ == "__main__": - main() \ No newline at end of file + main() From 0b65a02f71c3ec37ea6b0e1a4ffb39c8213b818f Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Wed, 28 Feb 2024 19:39:24 -0800 Subject: [PATCH 05/24] Use send_request --- .../_azure_appconfiguration_client.py | 102 ++++------ .../azure/appconfiguration/_models.py | 49 ++++- ...tor_configuration_settings_by_page_etag.py | 190 +++++++++++------- 3 files changed, 210 insertions(+), 131 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py index 3839f74438b6..ef88b6dc7813 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py @@ -4,6 +4,7 @@ # license information. # ------------------------------------------------------------------------- import binascii +import functools from datetime import datetime from typing import Any, Dict, List, Mapping, Optional, Union, cast, overload from typing_extensions import Literal @@ -19,12 +20,13 @@ ResourceModifiedError, ResourceNotModifiedError, ) +from azure.core.rest import HttpRequest, HttpResponse from azure.core.utils import CaseInsensitiveDict from ._azure_appconfiguration_error import ResourceReadOnlyError from ._azure_appconfiguration_requests import AppConfigRequestsCredentialsPolicy from ._generated import AzureAppConfiguration from ._generated.models import SnapshotUpdateParameters, SnapshotStatus -from ._models import ConfigurationSetting, ConfigurationSettingsFilter, ConfigurationSnapshot +from ._models import ConfigurationSetting, ConfigurationSettingsFilter, ConfigurationSnapshot, ConfigurationSettingPropertiesPaged from ._utils import ( prep_if_match, prep_if_none_match, @@ -109,23 +111,39 @@ def from_connection_string(cls, connection_string: str, **kwargs: Any) -> "Azure id_credential=id_credential, **kwargs, ) + + @distributed_trace + def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs) -> HttpResponse: + """Runs a network request using the client's existing pipeline. + + The request URL can be relative to the vault URL. The service API version used for the request is the same as + the client's unless otherwise specified. This method does not raise if the response is an error; to raise an + exception, call `raise_for_status()` on the returned response object. For more information about how to send + custom requests with this method, see https://aka.ms/azsdk/dpcodegen/python/send_request. + + :param request: The network request you want to make. + :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 + """ + return self._impl._send_request(request, stream=stream, **kwargs) @overload def list_configuration_settings( self, *, - page_etags: Optional[List[str]] = None, key_filter: Optional[str] = None, label_filter: Optional[str] = None, accept_datetime: Optional[Union[datetime, str]] = None, fields: Optional[List[str]] = None, **kwargs: Any, - ) -> Union[ItemPaged[ConfigurationSetting], List[Optional[ConfigurationSetting]]]: + ) -> ItemPaged[ConfigurationSetting]: """List the configuration settings stored in the configuration service, optionally filtered by key, label and accept_datetime. - :keyword page_etags: the page etags to compare with the targeted resource's etag. - :paramtype page_etags: list[str] or None :keyword key_filter: filter results based on their keys. '*' can be used as wildcard in the beginning or end of the filter :paramtype key_filter: str or None @@ -177,7 +195,7 @@ def list_configuration_settings( @distributed_trace def list_configuration_settings( self, *args, **kwargs - ) -> Union[ItemPaged[ConfigurationSetting], List[Optional[ItemPaged[ConfigurationSetting]]]]: + ) -> ItemPaged[ConfigurationSetting]: accept_datetime = kwargs.pop("accept_datetime", None) if isinstance(accept_datetime, datetime): accept_datetime = str(accept_datetime) @@ -185,7 +203,6 @@ def list_configuration_settings( if select: select = ["locked" if x == "read_only" else x for x in select] snapshot_name = kwargs.pop("snapshot_name", None) - page_etags = kwargs.pop("page_etags", None) try: if snapshot_name is not None: @@ -200,59 +217,24 @@ def list_configuration_settings( key_filter, kwargs = get_key_filter(*args, **kwargs) label_filter, kwargs = get_label_filter(*args, **kwargs) - if page_etags is None: - return self._impl.get_key_values( # type: ignore - key=key_filter, - label=label_filter, - accept_datetime=accept_datetime, - select=select, - cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), - **kwargs, - ) - - result = [] - continuation_token = None - index = 0 - try: - response = self._impl.get_key_values( # type: ignore - key=key_filter, - label=label_filter, - accept_datetime=accept_datetime, - select=select, - if_none_match=page_etags[index], - cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), - **kwargs, - ).by_page() - response.next() - result.append(response._current_page) - continuation_token = response.continuation_token - except ResourceNotModifiedError as e: - result.append(None) - link = e.response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - index += 1 - - while continuation_token: - try: - response = self._impl.get_key_values( # type: ignore - key=key_filter, - label=label_filter, - accept_datetime=accept_datetime, - select=select, - if_none_match=page_etags[index] if index < len(page_etags) else None, - cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), - **kwargs, - ).by_page(continuation_token = continuation_token) - response.next() - result.append(response._current_page) - continuation_token = response.continuation_token - except ResourceNotModifiedError as e: - result.append(None) - link = e.response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - index += 1 - - return result + # command = functools.partial(self._impl.get_key_values, **kwargs) + # return ItemPaged( + # command, + # key=key_filter, + # label=label_filter, + # accept_datetime=accept_datetime, + # select=select, + # cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), + # page_iterator_class=ConfigurationSettingPropertiesPaged, + # ) + return self._impl.get_key_values( # type: ignore + key=key_filter, + label=label_filter, + accept_datetime=accept_datetime, + select=select, + cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), + **kwargs, + ) except binascii.Error as exc: raise binascii.Error("Connection string secret has incorrect padding") from exc diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py index 10a26bb7dc89..2f812c0598d1 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py @@ -4,10 +4,11 @@ # ------------------------------------ import json from datetime import datetime -from typing import Any, Dict, List, Optional, Union, cast +from typing import Any, Dict, List, Optional, Union, cast, Callable from typing_extensions import Literal from azure.core.rest import HttpResponse +from azure.core.paging import PageIterator from ._generated._serialization import Model from ._generated.models import ( KeyValue, @@ -535,3 +536,49 @@ def _to_generated(self) -> GeneratedConfigurationSnapshot: retention_period=self.retention_period, tags=self.tags, ) + + +class ConfigurationSettingPropertiesPaged(PageIterator): + """An iterable of ConfigurationSetting properties.""" + + page_etag: str + """The etag of current page.""" + continuation_token: Optional[str] + """The continuation token needed by get_next().""" + + def __init__(self, command: Callable, **kwargs: Any) -> None: + super(ConfigurationSettingPropertiesPaged, self).__init__( + self._get_next_cb, + self._extract_data_cb, + continuation_token=kwargs.get("continuation_token"), + ) + self._command = command + self._key = kwargs.get("key_filter") + self._label = kwargs.get("label_filter") + self._accept_datetime = kwargs.get("accept_datetime") + self._select = kwargs.get("select") + self._cls = kwargs.get("cls") + self._response = None + + def _get_next_cb(self, continuation_token, **kwargs): # pylint: disable=inconsistent-return-statements + if continuation_token is None: + return self._command + response = self._command( + key=self._key, + label=self._label, + accept_datetime=self._accept_datetime, + select=self._select, + cls=self._cls, + ) + self._response = response + self.page_etag = response.http_response.headers['Etag'] + return response + + def _extract_data_cb(self, pipeline_response): + # convert result + # return pipeline_response + deserialized = AzureAppConfigurationMixinABC._deserialize("KeyValueListResult", pipeline_response) + list_of_elem = deserialized.items + if self.cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.next_link or None, iter(list_of_elem) diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py index 56dbd0ba7c4e..86ec1545bfb3 100644 --- a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py +++ b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py @@ -1,5 +1,8 @@ import os +import json from azure.appconfiguration import AzureAppConfigurationClient, ConfigurationSetting +from azure.core.exceptions import ResourceNotModifiedError +from azure.core.rest import HttpRequest from dotenv import find_dotenv, load_dotenv @@ -7,84 +10,131 @@ def main(): load_dotenv(find_dotenv()) CONNECTION_STRING = os.environ["APPCONFIGURATION_CONNECTION_STRING"] - client = AzureAppConfigurationClient.from_connection_string(CONNECTION_STRING) + with AzureAppConfigurationClient.from_connection_string(CONNECTION_STRING) as client: - # prepare 400 configuration settings - for i in range(400): + # prepare 400 configuration settings + for i in range(400): + client.add_configuration_setting( + ConfigurationSetting( + key=f"sample_key_{str(i)}", + label=f"sample_label_{str(i)}", + ) + ) + # there will have 4 pages while listing, there are 100 configuration settings per page. + + # get page etags + print("**********************get page etags*****************************") + page_etags = [] + items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") + iterator = items.by_page() + for page in iterator: + etag = iterator._response.http_response.headers['Etag'] + page_etags.append(etag) + print(f"ETag: {etag}") + + # monitor page updates + print("**********************monitor page before updates*****************************") + + continuation_token = None + index = 0 + request = HttpRequest( + method="GET", + url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", + headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + ) + first_page_response = client.send_request(request) + if first_page_response.status_code == 304: + print("No change found.") + if first_page_response.status_code == 200: + print("This page has changes.") + items = json.loads(bytearray(response.content))["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + + link = first_page_response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 + while continuation_token: + request = HttpRequest( + method="GET", + url=f"{continuation_token}", + headers={"If-None-Match": page_etags[index]} + ) + index += 1 + response = client.send_request(request) + if response.status_code == 304: + print("No change found.") + if response.status_code == 200: + print("This page has changes.") + items = json.loads(bytearray(response.content))["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + link = response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + + # add a configuration setting + print("**********************add a configuration setting*****************************") client.add_configuration_setting( ConfigurationSetting( - key=f"sample_key_{str(i)}", - label=f"sample_label_{str(i)}", + key="sample_key_201", + label="sample_label_202", ) ) - # there will have 4 pages while listing, there are 100 configuration settings per page. - - # get page etags - print("**********************get page etags*****************************") - page_etags = [] - items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") - iterator = items.by_page() - for page in iterator: - etag = iterator._response.http_response.headers['Etag'] - page_etags.append(etag) - print(f"ETag: {etag}") - - # ETag: "P3Oae4jiSypN6U1OApprRj2k7548_x3IYkn6NHp-wAU" next_link: /kv?key=sample_key_*&label=sample_label_*&api-version=2023-10-01&after=c2FtcGxlX2tleV8xODgKc2FtcGxlX2xhYmVsXzE4OA%3D%3D - # ETag: "x1HUZXjADggqDwAZfSArFfFgZKhLz439uDIpNY80hqc" next_link: /kv?key=sample_key_*&label=sample_label_*&api-version=2023-10-01&after=c2FtcGxlX2tleV8yNzQKc2FtcGxlX2xhYmVsXzI3NA%3D%3D - # ETag: "B37CWEtuQhXSOWv2f1T0QBlEMGFUbC1W0UVkKvSAWMM" next_link: /kv?key=sample_key_*&label=sample_label_*&api-version=2023-10-01&after=c2FtcGxlX2tleV8zNjQKc2FtcGxlX2xhYmVsXzM2NA%3D%3D - # ETag: "X-rxvugJpqrNoZwapRGx5oHI0wDnQRPiBo_MdWXZzoc" next_link: /kv?key=sample_key_*&label=sample_label_*&api-version=2023-10-01&after=c2FtcGxlX2tleV85NQpzYW1wbGVfbGFiZWxfOTU%3D - # ETag: "GoIDT8F8w0Jko6tIF3FgZz5hrPQgCN-WLTxiwK71vhw" next_link: None - - # monitor page updates - print("**********************monitor page before updates*****************************") - response = client.list_configuration_settings(page_etags=page_etags, key_filter="sample_key_*", label_filter="sample_label_*") - for page in response: - if page: - print("This page has changes.") - for item in page: - print(f"Key: {item.key}, Label: {item.label}") - else: - print("No change found.") - - # add a configuration setting - print("**********************add a configuration setting*****************************") - client.add_configuration_setting( - ConfigurationSetting( - key="sample_key_401", - label="sample_label_402", + + # print page etags after updates + print("*****************get page etags after updates**********************************") + items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") + iterator = items.by_page() + for page in iterator: + etag = iterator._response.http_response.headers['Etag'] + print(f"ETag: {etag}") + + # monitor page updates + print("**********************monitor page after updates*****************************") + continuation_token = None + index = 0 + request = HttpRequest( + method="GET", + url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", + headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} ) - ) - - # print page etags after updates - print("*****************print page etags after updates**********************************") - items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") - iterator = items.by_page() - for page in iterator: - etag = iterator._response.http_response.headers['Etag'] - print(f"ETag: {etag}") - - # monitor page updates - print("**********************monitor page updates*****************************") - response = client.list_configuration_settings(page_etags=page_etags, key_filter="sample_key_*", label_filter="sample_label_*") - # List[ItemPages[ConfigurationSetting]] - for page in response: - if page: + first_page_response = client.send_request(request) + if first_page_response.status_code == 304: + print("No change found.") + if first_page_response.status_code == 200: print("This page has changes.") - for item in page: - print(f"Key: {item.key}, Label: {item.label}") - else: - print("No change found.") + items = json.loads(bytearray(first_page_response.content))["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + + link = first_page_response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 + while continuation_token: + request = HttpRequest( + method="GET", + url=f"{continuation_token}", + headers={"If-None-Match": page_etags[index]} + ) + index += 1 + response = client.send_request(request) + if response.status_code == 304: + print("No change found.") + if response.status_code == 200: + print("This page has changes.") + items = json.loads(bytearray(response.content))["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + link = response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None - # clean up - print("*************************clean up**************************") - count = 0 - for item in client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*"): - client.delete_configuration_setting(item.key, label=item.label) - count += 1 - print(count) - - items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") - print(items is None) + # clean up + print("*************************clean up**************************") + count = 0 + for item in client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*"): + client.delete_configuration_setting(item.key, label=item.label) + count += 1 + print(count) if __name__ == "__main__": From faddb977f7f34eb4959b70cc6f296634f5940484 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 29 Feb 2024 10:39:18 -0800 Subject: [PATCH 06/24] Solution2- pass one page etag per page call --- .../_azure_appconfiguration_client.py | 35 +++- ...tor_configuration_settings_by_page_etag.py | 198 ++++++++++++------ 2 files changed, 164 insertions(+), 69 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py index ef88b6dc7813..6a917ca41ab5 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py @@ -135,6 +135,7 @@ def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs) def list_configuration_settings( self, *, + page_etag: Optional[str] = None, key_filter: Optional[str] = None, label_filter: Optional[str] = None, accept_datetime: Optional[Union[datetime, str]] = None, @@ -144,6 +145,8 @@ def list_configuration_settings( """List the configuration settings stored in the configuration service, optionally filtered by key, label and accept_datetime. + :keyword page_etag: the page etags to compare with the targeted resource's etag. + :paramtype page_etag: str or None :keyword key_filter: filter results based on their keys. '*' can be used as wildcard in the beginning or end of the filter :paramtype key_filter: str or None @@ -216,22 +219,34 @@ def list_configuration_settings( key_filter, kwargs = get_key_filter(*args, **kwargs) label_filter, kwargs = get_label_filter(*args, **kwargs) + page_etag = kwargs.pop("page_etag", None) + + if page_etag is None: + # command = functools.partial(self._impl.get_key_values, **kwargs) + # return ItemPaged( + # command, + # key=key_filter, + # label=label_filter, + # accept_datetime=accept_datetime, + # select=select, + # cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), + # page_iterator_class=ConfigurationSettingPropertiesPaged, + # ) + return self._impl.get_key_values( # type: ignore + key=key_filter, + label=label_filter, + accept_datetime=accept_datetime, + select=select, + cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), + **kwargs, + ) - # command = functools.partial(self._impl.get_key_values, **kwargs) - # return ItemPaged( - # command, - # key=key_filter, - # label=label_filter, - # accept_datetime=accept_datetime, - # select=select, - # cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), - # page_iterator_class=ConfigurationSettingPropertiesPaged, - # ) return self._impl.get_key_values( # type: ignore key=key_filter, label=label_filter, accept_datetime=accept_datetime, select=select, + if_none_match=page_etag, cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), **kwargs, ) diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py index 86ec1545bfb3..89d12da33514 100644 --- a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py +++ b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py @@ -35,49 +35,88 @@ def main(): # monitor page updates print("**********************monitor page before updates*****************************") - continuation_token = None + # continuation_token = None + # index = 0 + # request = HttpRequest( + # method="GET", + # url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", + # headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + # ) + # first_page_response = client.send_request(request) + # if first_page_response.status_code == 304: + # print("No change found.") + # if first_page_response.status_code == 200: + # print("This page has changes.") + # items = json.loads(bytearray(response.content))["items"] + # for item in items: + # print(f"Key: {item['key']}, Label: {item['label']}") + + # link = first_page_response.headers.get('Link', None) + # continuation_token = link[1:link.index(">")] if link else None + # index += 1 + # while continuation_token: + # request = HttpRequest( + # method="GET", + # url=f"{continuation_token}", + # headers={"If-None-Match": page_etags[index]} + # ) + # index += 1 + # response = client.send_request(request) + # if response.status_code == 304: + # print("No change found.") + # if response.status_code == 200: + # print("This page has changes.") + # items = json.loads(bytearray(response.content))["items"] + # for item in items: + # print(f"Key: {item['key']}, Label: {item['label']}") + # link = response.headers.get('Link', None) + # continuation_token = link[1:link.index(">")] if link else None + + # solution 2: pass one page etag per API call index = 0 - request = HttpRequest( - method="GET", - url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", - headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} - ) - first_page_response = client.send_request(request) - if first_page_response.status_code == 304: + try: + first_page_response = client.list_configuration_settings( + key_filter="sample_key_*", + label_filter="sample_label_*", + page_etag=page_etags[index] if index < len(page_etags) else None, + ).by_page() + next(first_page_response) print("No change found.") - if first_page_response.status_code == 200: + continuation_token = first_page_response.continuation_token + for item in first_page_response._current_page: + print(f"Key: {item.key}, Label: {item.label}") + except ResourceNotModifiedError as e: print("This page has changes.") - items = json.loads(bytearray(response.content))["items"] - for item in items: - print(f"Key: {item['key']}, Label: {item['label']}") - - link = first_page_response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None + link = e.response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 + while continuation_token: - request = HttpRequest( - method="GET", - url=f"{continuation_token}", - headers={"If-None-Match": page_etags[index]} - ) - index += 1 - response = client.send_request(request) - if response.status_code == 304: + try: + response = client.list_configuration_settings( + key_filter="sample_key_*", + label_filter="sample_label_*", + page_etag=page_etags[index] if index < len(page_etags) else None, + ).by_page(continuation_token=continuation_token) + next(response) print("No change found.") - if response.status_code == 200: + continuation_token = response.continuation_token + for item in response._current_page: + print(f"Key: {item.key}, Label: {item.label}") + except ResourceNotModifiedError as e: print("This page has changes.") - items = json.loads(bytearray(response.content))["items"] - for item in items: - print(f"Key: {item['key']}, Label: {item['label']}") - link = response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None + link = e.response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + + index += 1 # add a configuration setting print("**********************add a configuration setting*****************************") client.add_configuration_setting( ConfigurationSetting( key="sample_key_201", - label="sample_label_202", + label="sample_label_225", ) ) @@ -91,42 +130,83 @@ def main(): # monitor page updates print("**********************monitor page after updates*****************************") - continuation_token = None + # solution 1: send_request + # continuation_token = None + # index = 0 + # request = HttpRequest( + # method="GET", + # url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", + # headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + # ) + # first_page_response = client.send_request(request) + # if first_page_response.status_code == 304: + # print("No change found.") + # if first_page_response.status_code == 200: + # print("This page has changes.") + # items = json.loads(bytearray(first_page_response.content))["items"] + # for item in items: + # print(f"Key: {item['key']}, Label: {item['label']}") + + # link = first_page_response.headers.get('Link', None) + # continuation_token = link[1:link.index(">")] if link else None + # index += 1 + # while continuation_token: + # request = HttpRequest( + # method="GET", + # url=f"{continuation_token}", + # headers={"If-None-Match": page_etags[index]} + # ) + # index += 1 + # response = client.send_request(request) + # if response.status_code == 304: + # print("No change found.") + # if response.status_code == 200: + # print("This page has changes.") + # items = json.loads(bytearray(response.content))["items"] + # for item in items: + # print(f"Key: {item['key']}, Label: {item['label']}") + # link = response.headers.get('Link', None) + # continuation_token = link[1:link.index(">")] if link else None + + # solution 2: pass one page etag per API call index = 0 - request = HttpRequest( - method="GET", - url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", - headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} - ) - first_page_response = client.send_request(request) - if first_page_response.status_code == 304: + try: + first_page_response = client.list_configuration_settings( + key_filter="sample_key_*", + label_filter="sample_label_*", + page_etag=page_etags[index] if index < len(page_etags) else None, + ).by_page() + next(first_page_response) print("No change found.") - if first_page_response.status_code == 200: + continuation_token = first_page_response.continuation_token + for item in first_page_response._current_page: + print(f"Key: {item.key}, Label: {item.label}") + except ResourceNotModifiedError as e: print("This page has changes.") - items = json.loads(bytearray(first_page_response.content))["items"] - for item in items: - print(f"Key: {item['key']}, Label: {item['label']}") - - link = first_page_response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None + link = e.response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 + while continuation_token: - request = HttpRequest( - method="GET", - url=f"{continuation_token}", - headers={"If-None-Match": page_etags[index]} - ) - index += 1 - response = client.send_request(request) - if response.status_code == 304: + try: + response = client.list_configuration_settings( + key_filter="sample_key_*", + label_filter="sample_label_*", + page_etag=page_etags[index] if index < len(page_etags) else None, + ).by_page(continuation_token=continuation_token) + next(response) print("No change found.") - if response.status_code == 200: + continuation_token = response.continuation_token + for item in response._current_page: + print(f"Key: {item.key}, Label: {item.label}") + except ResourceNotModifiedError as e: print("This page has changes.") - items = json.loads(bytearray(response.content))["items"] - for item in items: - print(f"Key: {item['key']}, Label: {item['label']}") - link = response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None + link = e.response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + + index += 1 + # clean up print("*************************clean up**************************") From 04b1d91020014d899dd534464e688c46a358ef61 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 29 Feb 2024 17:45:39 -0800 Subject: [PATCH 07/24] Revert patches --- .../_generated/operations/_patch.py | 170 +----------------- 1 file changed, 2 insertions(+), 168 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py index 68b442ca50a0..f7dd32510333 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py @@ -6,175 +6,9 @@ Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ -from typing import Any, Iterable, List, Optional, Union -import urllib.parse +from typing import List -from azure.core.exceptions import ( - ClientAuthenticationError, - HttpResponseError, - ResourceExistsError, - ResourceNotFoundError, - ResourceNotModifiedError, - map_error, -) -from azure.core.paging import ItemPaged -from azure.core.pipeline import PipelineResponse -from azure.core.rest import HttpRequest -from azure.core.tracing.decorator import distributed_trace -from azure.core.utils import case_insensitive_dict - -from ._azure_app_configuration_operations import ( - AzureAppConfigurationOperationsMixin as GeneratedAzureAppConfigOps, - build_get_key_values_request, - ClsType, - _SERIALIZER, -) -from .. import models as _models -from .._vendor import _convert_request - - -class AzureAppConfigurationOperationsMixin(GeneratedAzureAppConfigOps): # pylint: disable=too-many-public-methods - @distributed_trace - def get_key_values( - self, - key: Optional[str] = None, - label: Optional[str] = None, - after: Optional[str] = None, - accept_datetime: Optional[str] = None, - select: Optional[List[Union[str, _models.KeyValueFields]]] = None, - snapshot: Optional[str] = None, - if_match: Optional[str] = None, - if_none_match: Optional[str] = None, - **kwargs: Any - ) -> Iterable["_models.KeyValue"]: - """Gets a list of key-values. - - Gets a list of key-values. - - :param key: A filter used to match keys. Default value is None. - :type key: str - :param label: A filter used to match labels. Default value is None. - :type label: str - :param after: Instructs the server to return elements that appear after the element referred to - by the specified token. Default value is None. - :type after: str - :param accept_datetime: Requests the server to respond with the state of the resource at the - specified time. Default value is None. - :type accept_datetime: str - :param select: Used to select what fields are present in the returned resource(s). Default - value is None. - :type select: list[str or ~azure.appconfiguration.models.KeyValueFields] - :param snapshot: A filter used get key-values for a snapshot. The value should be the name of - the snapshot. Not valid when used with 'key' and 'label' filters. Default value is None. - :type snapshot: str - :param if_match: Used to perform an operation only if the targeted resource's etag matches the - value provided. Default value is None. - :type if_match: str - :param if_none_match: Used to perform an operation only if the targeted resource's etag does - not match the value provided. Default value is None. - :type if_none_match: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: An iterator like instance of either KeyValue or the result of cls(response) - :rtype: ~azure.core.paging.ItemPaged[~azure.appconfiguration.models.KeyValue] - :raises ~azure.core.exceptions.HttpResponseError: - """ - _headers = kwargs.pop("headers", {}) or {} - _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - - api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version)) - cls: ClsType[_models.KeyValueListResult] = kwargs.pop("cls", None) - - error_map = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - def prepare_request(next_link=None): - if not next_link: - - _request = build_get_key_values_request( - key=key, - label=label, - after=after, - accept_datetime=accept_datetime, - select=select, - snapshot=snapshot, - if_match=if_match, - if_none_match=if_none_match, - sync_token=self._config.sync_token, - api_version=api_version, - headers=_headers, - params=_params, - ) - _request = _convert_request(_request) - 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) - - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - - _next_request_params["api-version"] = self._config.api_version - - # Construct headers - if if_match is not None: - _headers["If-Match"] = _SERIALIZER.header("if_match", if_match, "str") - if if_none_match is not None: - _headers["If-None-Match"] = _SERIALIZER.header("if_none_match", if_none_match, "str") - _request = HttpRequest( - "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params, headers=_headers - ) - _request = _convert_request(_request) - 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) - _request.method = "GET" - return _request - - def extract_data(pipeline_response): - deserialized = self._deserialize("KeyValueListResult", pipeline_response) - list_of_elem = deserialized.items - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.next_link or None, iter(list_of_elem) - - def get_next(next_link=None): - _request = prepare_request(next_link) - - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - 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) - error = self._deserialize.failsafe_deserialize(_models.Error, pipeline_response) - raise HttpResponseError(response=response, model=error) - - return pipeline_response - - return ItemPaged(get_next, extract_data) - -__all__: List[str] = [ - "AzureAppConfigurationOperationsMixin", -] # Add all objects you want publicly available to users at this package level +__all__: List[str] = [] # Add all objects you want publicly available to users at this package level def patch_sdk(): From 4c424b49831a6a60c523849497c6af22568ca628 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Mon, 4 Mar 2024 15:06:25 -0800 Subject: [PATCH 08/24] Update monitor_configuration_settings_by_page_etag.py --- .../monitor_configuration_settings_by_page_etag.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py index 89d12da33514..4597f6ba958e 100644 --- a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py +++ b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py @@ -47,7 +47,7 @@ def main(): # print("No change found.") # if first_page_response.status_code == 200: # print("This page has changes.") - # items = json.loads(bytearray(response.content))["items"] + # items = first_page_response.json()["items"] # for item in items: # print(f"Key: {item['key']}, Label: {item['label']}") @@ -66,7 +66,7 @@ def main(): # print("No change found.") # if response.status_code == 200: # print("This page has changes.") - # items = json.loads(bytearray(response.content))["items"] + # items = response.json()["items"] # for item in items: # print(f"Key: {item['key']}, Label: {item['label']}") # link = response.headers.get('Link', None) @@ -143,7 +143,7 @@ def main(): # print("No change found.") # if first_page_response.status_code == 200: # print("This page has changes.") - # items = json.loads(bytearray(first_page_response.content))["items"] + # items = first_page_response.json()["items"] # for item in items: # print(f"Key: {item['key']}, Label: {item['label']}") @@ -162,7 +162,7 @@ def main(): # print("No change found.") # if response.status_code == 200: # print("This page has changes.") - # items = json.loads(bytearray(response.content))["items"] + # items = response.json()["items"] # for item in items: # print(f"Key: {item['key']}, Label: {item['label']}") # link = response.headers.get('Link', None) From f1b554e8b27b15c8f3553180eff68271ec3a44bd Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Wed, 6 Mar 2024 15:57:40 -0800 Subject: [PATCH 09/24] Use custom iterator --- .../_azure_appconfiguration_client.py | 40 ++-- .../azure/appconfiguration/_models.py | 36 +-- ...tor_configuration_settings_by_page_etag.py | 207 ++++++------------ 3 files changed, 99 insertions(+), 184 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py index 6a917ca41ab5..e4058e1f4f2e 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py @@ -135,7 +135,6 @@ def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs) def list_configuration_settings( self, *, - page_etag: Optional[str] = None, key_filter: Optional[str] = None, label_filter: Optional[str] = None, accept_datetime: Optional[Union[datetime, str]] = None, @@ -145,8 +144,6 @@ def list_configuration_settings( """List the configuration settings stored in the configuration service, optionally filtered by key, label and accept_datetime. - :keyword page_etag: the page etags to compare with the targeted resource's etag. - :paramtype page_etag: str or None :keyword key_filter: filter results based on their keys. '*' can be used as wildcard in the beginning or end of the filter :paramtype key_filter: str or None @@ -219,37 +216,26 @@ def list_configuration_settings( key_filter, kwargs = get_key_filter(*args, **kwargs) label_filter, kwargs = get_label_filter(*args, **kwargs) - page_etag = kwargs.pop("page_etag", None) - if page_etag is None: - # command = functools.partial(self._impl.get_key_values, **kwargs) - # return ItemPaged( - # command, - # key=key_filter, - # label=label_filter, - # accept_datetime=accept_datetime, - # select=select, - # cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), - # page_iterator_class=ConfigurationSettingPropertiesPaged, - # ) - return self._impl.get_key_values( # type: ignore - key=key_filter, - label=label_filter, - accept_datetime=accept_datetime, - select=select, - cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), - **kwargs, - ) - - return self._impl.get_key_values( # type: ignore + command = functools.partial(self._impl.get_key_values, **kwargs) + return ItemPaged( + command, key=key_filter, label=label_filter, accept_datetime=accept_datetime, select=select, - if_none_match=page_etag, cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), - **kwargs, + page_iterator_class=ConfigurationSettingPropertiesPaged, ) + # return self._impl.get_key_values( # type: ignore + # key=key_filter, + # label=label_filter, + # accept_datetime=accept_datetime, + # select=select, + # cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), + # **kwargs, + # ) + except binascii.Error as exc: raise binascii.Error("Connection string secret has incorrect padding") from exc diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py index 2f812c0598d1..481beab5fe75 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py @@ -543,9 +543,7 @@ class ConfigurationSettingPropertiesPaged(PageIterator): page_etag: str """The etag of current page.""" - continuation_token: Optional[str] - """The continuation token needed by get_next().""" - + def __init__(self, command: Callable, **kwargs: Any) -> None: super(ConfigurationSettingPropertiesPaged, self).__init__( self._get_next_cb, @@ -558,27 +556,33 @@ def __init__(self, command: Callable, **kwargs: Any) -> None: self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") self._cls = kwargs.get("cls") - self._response = None + def _get_next_cb(self, continuation_token, **kwargs): # pylint: disable=inconsistent-return-statements - if continuation_token is None: - return self._command - response = self._command( + + response = self._command( key=self._key, label=self._label, accept_datetime=self._accept_datetime, select=self._select, cls=self._cls, - ) - self._response = response - self.page_etag = response.http_response.headers['Etag'] + ).by_page(continuation_token=continuation_token) + # print(f"continuation_token: {continuation_token}") + next(response) + if response._did_a_call_already: + self.page_etag = response._response.http_response.headers['Etag'] return response + def _extract_data_cb(self, pipeline_response): # convert result - # return pipeline_response - deserialized = AzureAppConfigurationMixinABC._deserialize("KeyValueListResult", pipeline_response) - list_of_elem = deserialized.items - if self.cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.next_link or None, iter(list_of_elem) + + # self.etag, deserialized = pipeline_response + # breakpoint() + # if self._cls: + # list_of_elem = [self._cls(e) for e in pipeline_response.items] # type: ignore + # else: + # list_of_elem = iter(pipeline_response.items) + # return pipeline_response.next_link or None, list_of_elem + + return pipeline_response.continuation_token, pipeline_response._current_page diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py index 4597f6ba958e..525e60614b58 100644 --- a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py +++ b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py @@ -28,95 +28,61 @@ def main(): items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") iterator = items.by_page() for page in iterator: - etag = iterator._response.http_response.headers['Etag'] + # etag = iterator._response.http_response.headers['Etag'] + # page_etags.append(etag) + # print(f"ETag: {etag}") + + etag = iterator.page_etag page_etags.append(etag) print(f"ETag: {etag}") + # monitor page updates print("**********************monitor page before updates*****************************") - # continuation_token = None - # index = 0 - # request = HttpRequest( - # method="GET", - # url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", - # headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} - # ) - # first_page_response = client.send_request(request) - # if first_page_response.status_code == 304: - # print("No change found.") - # if first_page_response.status_code == 200: - # print("This page has changes.") - # items = first_page_response.json()["items"] - # for item in items: - # print(f"Key: {item['key']}, Label: {item['label']}") - - # link = first_page_response.headers.get('Link', None) - # continuation_token = link[1:link.index(">")] if link else None - # index += 1 - # while continuation_token: - # request = HttpRequest( - # method="GET", - # url=f"{continuation_token}", - # headers={"If-None-Match": page_etags[index]} - # ) - # index += 1 - # response = client.send_request(request) - # if response.status_code == 304: - # print("No change found.") - # if response.status_code == 200: - # print("This page has changes.") - # items = response.json()["items"] - # for item in items: - # print(f"Key: {item['key']}, Label: {item['label']}") - # link = response.headers.get('Link', None) - # continuation_token = link[1:link.index(">")] if link else None - - # solution 2: pass one page etag per API call + continuation_token = None index = 0 - try: - first_page_response = client.list_configuration_settings( - key_filter="sample_key_*", - label_filter="sample_label_*", - page_etag=page_etags[index] if index < len(page_etags) else None, - ).by_page() - next(first_page_response) + request = HttpRequest( + method="GET", + url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", + headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + ) + first_page_response = client.send_request(request) + if first_page_response.status_code == 304: print("No change found.") - continuation_token = first_page_response.continuation_token - for item in first_page_response._current_page: - print(f"Key: {item.key}, Label: {item.label}") - except ResourceNotModifiedError as e: + if first_page_response.status_code == 200: print("This page has changes.") - link = e.response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - - index += 1 + items = first_page_response.json()["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + link = first_page_response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 while continuation_token: - try: - response = client.list_configuration_settings( - key_filter="sample_key_*", - label_filter="sample_label_*", - page_etag=page_etags[index] if index < len(page_etags) else None, - ).by_page(continuation_token=continuation_token) - next(response) + request = HttpRequest( + method="GET", + url=f"{continuation_token}", + headers={"If-None-Match": page_etags[index]} + ) + index += 1 + response = client.send_request(request) + if response.status_code == 304: print("No change found.") - continuation_token = response.continuation_token - for item in response._current_page: - print(f"Key: {item.key}, Label: {item.label}") - except ResourceNotModifiedError as e: + if response.status_code == 200: print("This page has changes.") - link = e.response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - - index += 1 + items = response.json()["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + link = response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None # add a configuration setting print("**********************add a configuration setting*****************************") client.add_configuration_setting( ConfigurationSetting( key="sample_key_201", - label="sample_label_225", + label="sample_label_205", ) ) @@ -125,88 +91,47 @@ def main(): items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") iterator = items.by_page() for page in iterator: - etag = iterator._response.http_response.headers['Etag'] + etag = iterator.page_etag print(f"ETag: {etag}") # monitor page updates print("**********************monitor page after updates*****************************") - # solution 1: send_request - # continuation_token = None - # index = 0 - # request = HttpRequest( - # method="GET", - # url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", - # headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} - # ) - # first_page_response = client.send_request(request) - # if first_page_response.status_code == 304: - # print("No change found.") - # if first_page_response.status_code == 200: - # print("This page has changes.") - # items = first_page_response.json()["items"] - # for item in items: - # print(f"Key: {item['key']}, Label: {item['label']}") - - # link = first_page_response.headers.get('Link', None) - # continuation_token = link[1:link.index(">")] if link else None - # index += 1 - # while continuation_token: - # request = HttpRequest( - # method="GET", - # url=f"{continuation_token}", - # headers={"If-None-Match": page_etags[index]} - # ) - # index += 1 - # response = client.send_request(request) - # if response.status_code == 304: - # print("No change found.") - # if response.status_code == 200: - # print("This page has changes.") - # items = response.json()["items"] - # for item in items: - # print(f"Key: {item['key']}, Label: {item['label']}") - # link = response.headers.get('Link', None) - # continuation_token = link[1:link.index(">")] if link else None - - # solution 2: pass one page etag per API call + continuation_token = None index = 0 - try: - first_page_response = client.list_configuration_settings( - key_filter="sample_key_*", - label_filter="sample_label_*", - page_etag=page_etags[index] if index < len(page_etags) else None, - ).by_page() - next(first_page_response) + request = HttpRequest( + method="GET", + url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", + headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + ) + first_page_response = client.send_request(request) + if first_page_response.status_code == 304: print("No change found.") - continuation_token = first_page_response.continuation_token - for item in first_page_response._current_page: - print(f"Key: {item.key}, Label: {item.label}") - except ResourceNotModifiedError as e: + if first_page_response.status_code == 200: print("This page has changes.") - link = e.response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - - index += 1 + items = first_page_response.json()["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + link = first_page_response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 while continuation_token: - try: - response = client.list_configuration_settings( - key_filter="sample_key_*", - label_filter="sample_label_*", - page_etag=page_etags[index] if index < len(page_etags) else None, - ).by_page(continuation_token=continuation_token) - next(response) + request = HttpRequest( + method="GET", + url=f"{continuation_token}", + headers={"If-None-Match": page_etags[index]} + ) + index += 1 + response = client.send_request(request) + if response.status_code == 304: print("No change found.") - continuation_token = response.continuation_token - for item in response._current_page: - print(f"Key: {item.key}, Label: {item.label}") - except ResourceNotModifiedError as e: + if response.status_code == 200: print("This page has changes.") - link = e.response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - - index += 1 - + items = response.json()["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + link = response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None # clean up print("*************************clean up**************************") From 4166d437acfa1706c5c412ec41dae2b4f239b014 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Wed, 6 Mar 2024 16:57:09 -0800 Subject: [PATCH 10/24] Fix wrong kwarg name bug --- .../_azure_appconfiguration_client.py | 16 ++++++++-------- .../azure/appconfiguration/_models.py | 11 +++++------ ...onitor_configuration_settings_by_page_etag.py | 4 ---- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py index e4058e1f4f2e..e0448f04918d 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py @@ -227,14 +227,14 @@ def list_configuration_settings( cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), page_iterator_class=ConfigurationSettingPropertiesPaged, ) - # return self._impl.get_key_values( # type: ignore - # key=key_filter, - # label=label_filter, - # accept_datetime=accept_datetime, - # select=select, - # cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), - # **kwargs, - # ) + return self._impl.get_key_values( # type: ignore + key=key_filter, + label=label_filter, + accept_datetime=accept_datetime, + select=select, + cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), + **kwargs, + ) except binascii.Error as exc: raise binascii.Error("Connection string secret has incorrect padding") from exc diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py index 481beab5fe75..83716b68d6d5 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py @@ -551,14 +551,15 @@ def __init__(self, command: Callable, **kwargs: Any) -> None: continuation_token=kwargs.get("continuation_token"), ) self._command = command - self._key = kwargs.get("key_filter") - self._label = kwargs.get("label_filter") + self._key = kwargs.get("key") + self._label = kwargs.get("label") self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") self._cls = kwargs.get("cls") + self._kwargs = kwargs - def _get_next_cb(self, continuation_token, **kwargs): # pylint: disable=inconsistent-return-statements + def _get_next_cb(self, continuation_token): # pylint: disable=inconsistent-return-statements response = self._command( key=self._key, @@ -567,10 +568,8 @@ def _get_next_cb(self, continuation_token, **kwargs): # pylint: disable=inconsi select=self._select, cls=self._cls, ).by_page(continuation_token=continuation_token) - # print(f"continuation_token: {continuation_token}") next(response) - if response._did_a_call_already: - self.page_etag = response._response.http_response.headers['Etag'] + self.page_etag = response._response.http_response.headers['Etag'] return response diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py index 525e60614b58..9f067fd4a8f4 100644 --- a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py +++ b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py @@ -28,10 +28,6 @@ def main(): items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") iterator = items.by_page() for page in iterator: - # etag = iterator._response.http_response.headers['Etag'] - # page_etags.append(etag) - # print(f"ETag: {etag}") - etag = iterator.page_etag page_etags.append(etag) print(f"ETag: {etag}") From 33ef0e0e6bc32b39f78f5b6211d5f63e183bc76d Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Wed, 6 Mar 2024 18:43:51 -0800 Subject: [PATCH 11/24] Add async implementation --- .../_azure_appconfiguration_client.py | 23 ++- .../azure/appconfiguration/_models.py | 50 ++++-- .../_azure_appconfiguration_client_async.py | 34 +++- ...tor_configuration_settings_by_page_etag.py | 2 - ...nfiguration_settings_by_page_etag_async.py | 147 ++++++++++++++++++ 5 files changed, 225 insertions(+), 31 deletions(-) create mode 100644 sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag_async.py diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py index e0448f04918d..4e5e993c18dc 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py @@ -26,7 +26,12 @@ from ._azure_appconfiguration_requests import AppConfigRequestsCredentialsPolicy from ._generated import AzureAppConfiguration from ._generated.models import SnapshotUpdateParameters, SnapshotStatus -from ._models import ConfigurationSetting, ConfigurationSettingsFilter, ConfigurationSnapshot, ConfigurationSettingPropertiesPaged +from ._models import ( + ConfigurationSetting, + ConfigurationSettingsFilter, + ConfigurationSnapshot, + ConfigurationSettingPropertiesPaged, +) from ._utils import ( prep_if_match, prep_if_none_match, @@ -113,7 +118,7 @@ def from_connection_string(cls, connection_string: str, **kwargs: Any) -> "Azure ) @distributed_trace - def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs) -> HttpResponse: + def send_request(self, request: HttpRequest, **kwargs) -> HttpResponse: """Runs a network request using the client's existing pipeline. The request URL can be relative to the vault URL. The service API version used for the request is the same as @@ -129,7 +134,7 @@ def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs) :return: The response of your network call. Does not do error handling on your response. :rtype: ~azure.core.rest.HttpResponse """ - return self._impl._send_request(request, stream=stream, **kwargs) + return self._impl._send_request(request, **kwargs) @overload def list_configuration_settings( @@ -213,10 +218,8 @@ def list_configuration_settings( cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs], **kwargs, ) - key_filter, kwargs = get_key_filter(*args, **kwargs) label_filter, kwargs = get_label_filter(*args, **kwargs) - command = functools.partial(self._impl.get_key_values, **kwargs) return ItemPaged( command, @@ -224,17 +227,9 @@ def list_configuration_settings( label=label_filter, accept_datetime=accept_datetime, select=select, - cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), + cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs], page_iterator_class=ConfigurationSettingPropertiesPaged, ) - return self._impl.get_key_values( # type: ignore - key=key_filter, - label=label_filter, - accept_datetime=accept_datetime, - select=select, - cls=kwargs.pop("cls", lambda objs: [ConfigurationSetting._from_generated(x) for x in objs]), - **kwargs, - ) except binascii.Error as exc: raise binascii.Error("Connection string secret has incorrect padding") from exc diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py index 83716b68d6d5..a0dc67c6ea8e 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py @@ -9,6 +9,7 @@ from azure.core.rest import HttpResponse from azure.core.paging import PageIterator +from azure.core.async_paging import AsyncPageIterator from ._generated._serialization import Model from ._generated.models import ( KeyValue, @@ -556,11 +557,9 @@ def __init__(self, command: Callable, **kwargs: Any) -> None: self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") self._cls = kwargs.get("cls") - self._kwargs = kwargs def _get_next_cb(self, continuation_token): # pylint: disable=inconsistent-return-statements - response = self._command( key=self._key, label=self._label, @@ -574,14 +573,41 @@ def _get_next_cb(self, continuation_token): # pylint: disable=inconsistent-retu def _extract_data_cb(self, pipeline_response): - # convert result - - # self.etag, deserialized = pipeline_response - # breakpoint() - # if self._cls: - # list_of_elem = [self._cls(e) for e in pipeline_response.items] # type: ignore - # else: - # list_of_elem = iter(pipeline_response.items) - # return pipeline_response.next_link or None, list_of_elem - + return pipeline_response.continuation_token, pipeline_response._current_page + + +class ConfigurationSettingPropertiesPagedAsync(AsyncPageIterator): + """An iterable of ConfigurationSetting properties.""" + + page_etag: str + """The etag of current page.""" + + def __init__(self, command: Callable, **kwargs: Any) -> None: + super(ConfigurationSettingPropertiesPagedAsync, self).__init__( + self._get_next_cb, + self._extract_data_cb, + continuation_token=kwargs.get("continuation_token"), + ) + self._command = command + self._key = kwargs.get("key") + self._label = kwargs.get("label") + self._accept_datetime = kwargs.get("accept_datetime") + self._select = kwargs.get("select") + self._cls = kwargs.get("cls") + + + async def _get_next_cb(self, continuation_token): # pylint: disable=inconsistent-return-statements + response = self._command( + key=self._key, + label=self._label, + accept_datetime=self._accept_datetime, + select=self._select, + cls=self._cls, + ).by_page(continuation_token=continuation_token) + await anext(response) + self.page_etag = response._response.http_response.headers['Etag'] + return response + + + async def _extract_data_cb(self, pipeline_response): return pipeline_response.continuation_token, pipeline_response._current_page diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py index d80fa76abfaf..d21248581103 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py @@ -4,6 +4,7 @@ # license information. # ------------------------------------------------------------------------- import binascii +import functools from datetime import datetime from typing import Any, Dict, List, Mapping, Optional, Union, cast, overload from typing_extensions import Literal @@ -21,13 +22,19 @@ ResourceNotFoundError, ResourceNotModifiedError, ) +from azure.core.rest import AsyncHttpResponse, HttpRequest from azure.core.utils import CaseInsensitiveDict from ._sync_token_async import AsyncSyncTokenPolicy from .._azure_appconfiguration_error import ResourceReadOnlyError from .._azure_appconfiguration_requests import AppConfigRequestsCredentialsPolicy from .._generated.aio import AzureAppConfiguration from .._generated.models import SnapshotUpdateParameters, SnapshotStatus -from .._models import ConfigurationSetting, ConfigurationSettingsFilter, ConfigurationSnapshot +from .._models import ( + ConfigurationSetting, + ConfigurationSettingsFilter, + ConfigurationSnapshot, + ConfigurationSettingPropertiesPagedAsync, +) from .._utils import ( prep_if_match, prep_if_none_match, @@ -116,6 +123,25 @@ def from_connection_string(cls, connection_string: str, **kwargs: Any) -> "Azure **kwargs, ) + @distributed_trace_async + async def send_request(self, request: HttpRequest, **kwargs) -> AsyncHttpResponse: + """Runs a network request using the client's existing pipeline. + + The request URL can be relative to the vault URL. The service API version used for the request is the same as + the client's unless otherwise specified. This method does not raise if the response is an error; to raise an + exception, call `raise_for_status()` on the returned response object. For more information about how to send + custom requests with this method, see https://aka.ms/azsdk/dpcodegen/python/send_request. + + :param request: The network request you want to make. + :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 + """ + return await self._impl._send_request(request, **kwargs) + @overload def list_configuration_settings( self, @@ -200,13 +226,15 @@ def list_configuration_settings(self, *args, **kwargs) -> AsyncItemPaged[Configu ) key_filter, kwargs = get_key_filter(*args, **kwargs) label_filter, kwargs = get_label_filter(*args, **kwargs) - return self._impl.get_key_values( # type: ignore + command = functools.partial(self._impl.get_key_values, **kwargs) + return AsyncItemPaged( + command, key=key_filter, label=label_filter, accept_datetime=accept_datetime, select=select, cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs], - **kwargs, + page_iterator_class=ConfigurationSettingPropertiesPagedAsync, ) except binascii.Error as exc: raise binascii.Error("Connection string secret has incorrect padding") from exc diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py index 9f067fd4a8f4..dd1a66ab47cd 100644 --- a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py +++ b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py @@ -1,7 +1,5 @@ import os -import json from azure.appconfiguration import AzureAppConfigurationClient, ConfigurationSetting -from azure.core.exceptions import ResourceNotModifiedError from azure.core.rest import HttpRequest from dotenv import find_dotenv, load_dotenv diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag_async.py b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag_async.py new file mode 100644 index 000000000000..1c0d28fbd3c5 --- /dev/null +++ b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag_async.py @@ -0,0 +1,147 @@ +# 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 asyncio +import os +from azure.appconfiguration import ConfigurationSetting +from azure.appconfiguration.aio import AzureAppConfigurationClient +from azure.core.rest import HttpRequest +from dotenv import find_dotenv, load_dotenv + + +async def main(): + load_dotenv(find_dotenv()) + CONNECTION_STRING = os.environ["APPCONFIGURATION_CONNECTION_STRING"] + + async with AzureAppConfigurationClient.from_connection_string(CONNECTION_STRING) as client: + + # prepare 400 configuration settings + for i in range(400): + await client.add_configuration_setting( + ConfigurationSetting( + key=f"sample_key_{str(i)}", + label=f"sample_label_{str(i)}", + ) + ) + # there will have 4 pages while listing, there are 100 configuration settings per page. + + # get page etags + print("**********************get page etags*****************************") + page_etags = [] + items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") + iterator = items.by_page() + async for page in iterator: + etag = iterator.page_etag + page_etags.append(etag) + print(f"ETag: {etag}") + + # monitor page updates + print("**********************monitor page before updates*****************************") + continuation_token = None + index = 0 + request = HttpRequest( + method="GET", + url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", + headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + ) + first_page_response = await client.send_request(request) + if first_page_response.status_code == 304: + print("No change found.") + if first_page_response.status_code == 200: + print("This page has changes.") + items = first_page_response.json()["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + + link = first_page_response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 + while continuation_token: + request = HttpRequest( + method="GET", + url=f"{continuation_token}", + headers={"If-None-Match": page_etags[index]} + ) + index += 1 + response = await client.send_request(request) + if response.status_code == 304: + print("No change found.") + if response.status_code == 200: + print("This page has changes.") + items = response.json()["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + link = response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + + # add a configuration setting + print("**********************add a configuration setting*****************************") + await client.add_configuration_setting( + ConfigurationSetting( + key="sample_key_201", + label="sample_label_202", + ) + ) + + # print page etags after updates + print("*****************get page etags after updates**********************************") + items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") + iterator = items.by_page() + async for page in iterator: + etag = iterator.page_etag + print(f"ETag: {etag}") + + # monitor page updates + print("**********************monitor page after updates*****************************") + continuation_token = None + index = 0 + request = HttpRequest( + method="GET", + url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", + headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + ) + first_page_response = await client.send_request(request) + if first_page_response.status_code == 304: + print("No change found.") + if first_page_response.status_code == 200: + print("This page has changes.") + items = first_page_response.json()["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + + link = first_page_response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 + while continuation_token: + request = HttpRequest( + method="GET", + url=f"{continuation_token}", + headers={"If-None-Match": page_etags[index]} + ) + index += 1 + response = await client.send_request(request) + if response.status_code == 304: + print("No change found.") + if response.status_code == 200: + print("This page has changes.") + items = response.json()["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + link = response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + + # clean up + print("*************************clean up**************************") + count = 0 + async for item in client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*"): + await client.delete_configuration_setting(item.key, label=item.label) + count += 1 + print(count) + +if __name__ == "__main__": + asyncio.run(main()) From 692317c0c18c645493bc2d9430b4f619ab4010e8 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Wed, 6 Mar 2024 18:47:57 -0800 Subject: [PATCH 12/24] Resolve cspell error --- .vscode/cspell.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.vscode/cspell.json b/.vscode/cspell.json index 8e0410c5896b..20c782b3e060 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -1631,6 +1631,12 @@ "azconfig" ] }, + { + "filename": "sdk/appconfiguration/azure-appconfiguration/**", + "words": [ + "kvset" + ] + }, { "filename": "sdk/personalizer/test-resources.json", "words": [ From 8bfc59794762f333d712dbdbc58418dc7011406f Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Wed, 6 Mar 2024 19:40:19 -0800 Subject: [PATCH 13/24] Move samples to live tests --- .../azure-appconfiguration/assets.json | 2 +- ...tor_configuration_settings_by_page_etag.py | 140 ----------------- ...nfiguration_settings_by_page_etag_async.py | 147 ------------------ .../test_azure_appconfiguration_client.py | 109 +++++++++++++ ...est_azure_appconfiguration_client_async.py | 109 +++++++++++++ 5 files changed, 219 insertions(+), 288 deletions(-) delete mode 100644 sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py delete mode 100644 sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag_async.py diff --git a/sdk/appconfiguration/azure-appconfiguration/assets.json b/sdk/appconfiguration/azure-appconfiguration/assets.json index c374a2eea98b..1493f31a8b20 100644 --- a/sdk/appconfiguration/azure-appconfiguration/assets.json +++ b/sdk/appconfiguration/azure-appconfiguration/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "python", "TagPrefix": "python/appconfiguration/azure-appconfiguration", - "Tag": "python/appconfiguration/azure-appconfiguration_6ae662d134" + "Tag": "python/appconfiguration/azure-appconfiguration_8137b21bd0" } diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py deleted file mode 100644 index dd1a66ab47cd..000000000000 --- a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag.py +++ /dev/null @@ -1,140 +0,0 @@ -import os -from azure.appconfiguration import AzureAppConfigurationClient, ConfigurationSetting -from azure.core.rest import HttpRequest -from dotenv import find_dotenv, load_dotenv - - -def main(): - load_dotenv(find_dotenv()) - CONNECTION_STRING = os.environ["APPCONFIGURATION_CONNECTION_STRING"] - - with AzureAppConfigurationClient.from_connection_string(CONNECTION_STRING) as client: - - # prepare 400 configuration settings - for i in range(400): - client.add_configuration_setting( - ConfigurationSetting( - key=f"sample_key_{str(i)}", - label=f"sample_label_{str(i)}", - ) - ) - # there will have 4 pages while listing, there are 100 configuration settings per page. - - # get page etags - print("**********************get page etags*****************************") - page_etags = [] - items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") - iterator = items.by_page() - for page in iterator: - etag = iterator.page_etag - page_etags.append(etag) - print(f"ETag: {etag}") - - - # monitor page updates - print("**********************monitor page before updates*****************************") - - continuation_token = None - index = 0 - request = HttpRequest( - method="GET", - url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", - headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} - ) - first_page_response = client.send_request(request) - if first_page_response.status_code == 304: - print("No change found.") - if first_page_response.status_code == 200: - print("This page has changes.") - items = first_page_response.json()["items"] - for item in items: - print(f"Key: {item['key']}, Label: {item['label']}") - - link = first_page_response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - index += 1 - while continuation_token: - request = HttpRequest( - method="GET", - url=f"{continuation_token}", - headers={"If-None-Match": page_etags[index]} - ) - index += 1 - response = client.send_request(request) - if response.status_code == 304: - print("No change found.") - if response.status_code == 200: - print("This page has changes.") - items = response.json()["items"] - for item in items: - print(f"Key: {item['key']}, Label: {item['label']}") - link = response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - - # add a configuration setting - print("**********************add a configuration setting*****************************") - client.add_configuration_setting( - ConfigurationSetting( - key="sample_key_201", - label="sample_label_205", - ) - ) - - # print page etags after updates - print("*****************get page etags after updates**********************************") - items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") - iterator = items.by_page() - for page in iterator: - etag = iterator.page_etag - print(f"ETag: {etag}") - - # monitor page updates - print("**********************monitor page after updates*****************************") - continuation_token = None - index = 0 - request = HttpRequest( - method="GET", - url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", - headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} - ) - first_page_response = client.send_request(request) - if first_page_response.status_code == 304: - print("No change found.") - if first_page_response.status_code == 200: - print("This page has changes.") - items = first_page_response.json()["items"] - for item in items: - print(f"Key: {item['key']}, Label: {item['label']}") - - link = first_page_response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - index += 1 - while continuation_token: - request = HttpRequest( - method="GET", - url=f"{continuation_token}", - headers={"If-None-Match": page_etags[index]} - ) - index += 1 - response = client.send_request(request) - if response.status_code == 304: - print("No change found.") - if response.status_code == 200: - print("This page has changes.") - items = response.json()["items"] - for item in items: - print(f"Key: {item['key']}, Label: {item['label']}") - link = response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - - # clean up - print("*************************clean up**************************") - count = 0 - for item in client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*"): - client.delete_configuration_setting(item.key, label=item.label) - count += 1 - print(count) - - -if __name__ == "__main__": - main() diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag_async.py b/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag_async.py deleted file mode 100644 index 1c0d28fbd3c5..000000000000 --- a/sdk/appconfiguration/azure-appconfiguration/samples/monitor_configuration_settings_by_page_etag_async.py +++ /dev/null @@ -1,147 +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. -# -------------------------------------------------------------------------- - -import asyncio -import os -from azure.appconfiguration import ConfigurationSetting -from azure.appconfiguration.aio import AzureAppConfigurationClient -from azure.core.rest import HttpRequest -from dotenv import find_dotenv, load_dotenv - - -async def main(): - load_dotenv(find_dotenv()) - CONNECTION_STRING = os.environ["APPCONFIGURATION_CONNECTION_STRING"] - - async with AzureAppConfigurationClient.from_connection_string(CONNECTION_STRING) as client: - - # prepare 400 configuration settings - for i in range(400): - await client.add_configuration_setting( - ConfigurationSetting( - key=f"sample_key_{str(i)}", - label=f"sample_label_{str(i)}", - ) - ) - # there will have 4 pages while listing, there are 100 configuration settings per page. - - # get page etags - print("**********************get page etags*****************************") - page_etags = [] - items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") - iterator = items.by_page() - async for page in iterator: - etag = iterator.page_etag - page_etags.append(etag) - print(f"ETag: {etag}") - - # monitor page updates - print("**********************monitor page before updates*****************************") - continuation_token = None - index = 0 - request = HttpRequest( - method="GET", - url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", - headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} - ) - first_page_response = await client.send_request(request) - if first_page_response.status_code == 304: - print("No change found.") - if first_page_response.status_code == 200: - print("This page has changes.") - items = first_page_response.json()["items"] - for item in items: - print(f"Key: {item['key']}, Label: {item['label']}") - - link = first_page_response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - index += 1 - while continuation_token: - request = HttpRequest( - method="GET", - url=f"{continuation_token}", - headers={"If-None-Match": page_etags[index]} - ) - index += 1 - response = await client.send_request(request) - if response.status_code == 304: - print("No change found.") - if response.status_code == 200: - print("This page has changes.") - items = response.json()["items"] - for item in items: - print(f"Key: {item['key']}, Label: {item['label']}") - link = response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - - # add a configuration setting - print("**********************add a configuration setting*****************************") - await client.add_configuration_setting( - ConfigurationSetting( - key="sample_key_201", - label="sample_label_202", - ) - ) - - # print page etags after updates - print("*****************get page etags after updates**********************************") - items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") - iterator = items.by_page() - async for page in iterator: - etag = iterator.page_etag - print(f"ETag: {etag}") - - # monitor page updates - print("**********************monitor page after updates*****************************") - continuation_token = None - index = 0 - request = HttpRequest( - method="GET", - url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", - headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} - ) - first_page_response = await client.send_request(request) - if first_page_response.status_code == 304: - print("No change found.") - if first_page_response.status_code == 200: - print("This page has changes.") - items = first_page_response.json()["items"] - for item in items: - print(f"Key: {item['key']}, Label: {item['label']}") - - link = first_page_response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - index += 1 - while continuation_token: - request = HttpRequest( - method="GET", - url=f"{continuation_token}", - headers={"If-None-Match": page_etags[index]} - ) - index += 1 - response = await client.send_request(request) - if response.status_code == 304: - print("No change found.") - if response.status_code == 200: - print("This page has changes.") - items = response.json()["items"] - for item in items: - print(f"Key: {item['key']}, Label: {item['label']}") - link = response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - - # clean up - print("*************************clean up**************************") - count = 0 - async for item in client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*"): - await client.delete_configuration_setting(item.key, label=item.label) - count += 1 - print(count) - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py index 073b669af7e1..6289c41ddb97 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py @@ -15,6 +15,7 @@ ResourceNotFoundError, ResourceExistsError, ) +from azure.core.rest import HttpRequest from azure.appconfiguration import ( ResourceReadOnlyError, AzureAppConfigurationClient, @@ -983,6 +984,114 @@ def test_list_snapshot_configuration_settings(self, appconfiguration_connection_ self.tear_down() + @app_config_decorator + @recorded_by_proxy + def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_connection_string): + with AzureAppConfigurationClient.from_connection_string(appconfiguration_connection_string) as client: + # prepare 200 configuration settings + for i in range(200): + client.add_configuration_setting( + ConfigurationSetting( + key=f"sample_key_{str(i)}", + label=f"sample_label_{str(i)}", + ) + ) + # there will have 2 pages while listing, there are 100 configuration settings per page. + + # get page etags + page_etags = [] + items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") + iterator = items.by_page() + for page in iterator: + etag = iterator.page_etag + page_etags.append(etag) + + # monitor page updates without changes + continuation_token = None + index = 0 + request = HttpRequest( + method="GET", + url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", + headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + ) + first_page_response = client.send_request(request) + assert first_page_response.status_code == 304 + + link = first_page_response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 + while continuation_token: + request = HttpRequest( + method="GET", + url=f"{continuation_token}", + headers={"If-None-Match": page_etags[index]} + ) + index += 1 + response = client.send_request(request) + assert response.status_code == 304 + + link = response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + + # do some changes + client.add_configuration_setting( + ConfigurationSetting( + key="sample_key_201", + label="sample_label_202", + ) + ) + # now we have three pages, 100 settings in first two pages and 1 setting in the last page + + # get page etags after updates + new_page_etags = [] + items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") + iterator = items.by_page() + for page in iterator: + etag = iterator.page_etag + new_page_etags.append(etag) + + assert page_etags[0] == new_page_etags[0] + assert page_etags[1] != new_page_etags[1] + assert page_etags[2] != new_page_etags[2] + + # monitor page after updates + continuation_token = None + index = 0 + request = HttpRequest( + method="GET", + url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", + headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + ) + first_page_response = client.send_request(request) + # 304 means the page doesn't have changes. + assert first_page_response.status_code == 304 + + link = first_page_response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 + while continuation_token: + request = HttpRequest( + method="GET", + url=f"{continuation_token}", + headers={"If-None-Match": page_etags[index]} + ) + index += 1 + response = client.send_request(request) + + # 200 means the page has changes. + assert response.status_code == 200 + items = response.json()["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + + link = response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + + # clean up + config_settings = client.list_configuration_settings() + for config_setting in config_settings: + client.delete_configuration_setting(key=config_setting.key, label=config_setting.label) + class TestAppConfigurationClientUnitTest: def test_type_error(self): diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py index 91af95ba5794..63f4f2a314a7 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py @@ -15,6 +15,7 @@ ResourceExistsError, AzureError, ) +from azure.core.rest import HttpRequest from azure.appconfiguration import ( ResourceReadOnlyError, ConfigurationSetting, @@ -1004,6 +1005,114 @@ async def test_list_snapshot_configuration_settings(self, appconfiguration_conne assert len(items) == 1 await self.tear_down() + + @app_config_decorator_async + @recorded_by_proxy_async + async def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_connection_string): + async with AzureAppConfigurationClient.from_connection_string(appconfiguration_connection_string) as client: + # prepare 200 configuration settings + for i in range(200): + await client.add_configuration_setting( + ConfigurationSetting( + key=f"async_sample_key_{str(i)}", + label=f"async_sample_label_{str(i)}", + ) + ) + # there will have 2 pages while listing, there are 100 configuration settings per page. + + # get page etags + page_etags = [] + items = client.list_configuration_settings(key_filter="async_sample_key_*", label_filter="async_sample_label_*") + iterator = items.by_page() + async for page in iterator: + etag = iterator.page_etag + page_etags.append(etag) + + # monitor page updates without changes + continuation_token = None + index = 0 + request = HttpRequest( + method="GET", + url="/kv?key=async_sample_key_%2A&label=async_sample_label_%2A&api-version=2023-10-01", + headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + ) + first_page_response = await client.send_request(request) + assert first_page_response.status_code == 304 + + link = first_page_response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 + while continuation_token: + request = HttpRequest( + method="GET", + url=f"{continuation_token}", + headers={"If-None-Match": page_etags[index]} + ) + index += 1 + response = await client.send_request(request) + assert response.status_code == 304 + + link = response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + + # do some changes + await client.add_configuration_setting( + ConfigurationSetting( + key="async_sample_key_201", + label="async_sample_label_202", + ) + ) + # now we have three pages, 100 settings in first two pages and 1 setting in the last page + + # get page etags after updates + new_page_etags = [] + items = client.list_configuration_settings(key_filter="async_sample_key_*", label_filter="async_sample_label_*") + iterator = items.by_page() + async for page in iterator: + etag = iterator.page_etag + new_page_etags.append(etag) + + assert page_etags[0] == new_page_etags[0] + assert page_etags[1] != new_page_etags[1] + assert page_etags[2] != new_page_etags[2] + + # monitor page after updates + continuation_token = None + index = 0 + request = HttpRequest( + method="GET", + url="/kv?key=async_sample_key_%2A&label=async_sample_label_%2A&api-version=2023-10-01", + headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + ) + first_page_response = await client.send_request(request) + # 304 means the page doesn't have changes. + assert first_page_response.status_code == 304 + + link = first_page_response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + index += 1 + while continuation_token: + request = HttpRequest( + method="GET", + url=f"{continuation_token}", + headers={"If-None-Match": page_etags[index]} + ) + index += 1 + response = await client.send_request(request) + + # 200 means the page has changes. + assert response.status_code == 200 + items = response.json()["items"] + for item in items: + print(f"Key: {item['key']}, Label: {item['label']}") + + link = response.headers.get('Link', None) + continuation_token = link[1:link.index(">")] if link else None + + # clean up + config_settings = client.list_configuration_settings() + async for config_setting in config_settings: + await client.delete_configuration_setting(key=config_setting.key, label=config_setting.label) class TestAppConfigurationClientUnitTest: From e0335e7c6d8c702d82eccd5824415d72e4739737 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Wed, 6 Mar 2024 19:44:15 -0800 Subject: [PATCH 14/24] Update CHANGELOG.md --- sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md index 7c254a7effdc..4c31c7806d14 100644 --- a/sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md @@ -1,16 +1,14 @@ # Release History -## 1.5.1 (Unreleased) +## 1.5.1 (2024-03-07) ### Features Added - -### Breaking Changes +- Exposed `send_request()` method in each client to send custom requests using the client's existing pipeline. +- Supported to get `page_etag` while iterating `list_configuration_setting()` result by page. ### Bugs Fixed - Fixed a bug in consuming "etag" value in sync operation `set_configuration_setting()`. -### Other Changes - ## 1.5.0 (2023-11-09) ### Other Changes From f7fd93fcc98fab568ccc42671c26a54d24a1dbd6 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 7 Mar 2024 17:06:57 -0800 Subject: [PATCH 15/24] Address comments --- .../_azure_appconfiguration_client.py | 6 +-- .../azure/appconfiguration/_models.py | 22 +++++------ .../_azure_appconfiguration_client_async.py | 6 +-- .../samples/send_request_sample.py | 38 ++++++++++++++++++ .../samples/send_request_sample_async.py | 39 +++++++++++++++++++ .../test_azure_appconfiguration_client.py | 4 +- ...est_azure_appconfiguration_client_async.py | 4 +- 7 files changed, 94 insertions(+), 25 deletions(-) create mode 100644 sdk/appconfiguration/azure-appconfiguration/samples/send_request_sample.py create mode 100644 sdk/appconfiguration/azure-appconfiguration/samples/send_request_sample_async.py diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py index 4e5e993c18dc..c8b0523f1627 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py @@ -118,7 +118,7 @@ def from_connection_string(cls, connection_string: str, **kwargs: Any) -> "Azure ) @distributed_trace - def send_request(self, request: HttpRequest, **kwargs) -> HttpResponse: + def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs) -> HttpResponse: """Runs a network request using the client's existing pipeline. The request URL can be relative to the vault URL. The service API version used for the request is the same as @@ -128,13 +128,11 @@ def send_request(self, request: HttpRequest, **kwargs) -> HttpResponse: :param request: The network request you want to make. :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 """ - return self._impl._send_request(request, **kwargs) + return self._impl._send_request(request, stream=stream, **kwargs) @overload def list_configuration_settings( diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py index a0dc67c6ea8e..36dc0c4fc20f 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py @@ -542,10 +542,10 @@ def _to_generated(self) -> GeneratedConfigurationSnapshot: class ConfigurationSettingPropertiesPaged(PageIterator): """An iterable of ConfigurationSetting properties.""" - page_etag: str + etag: str """The etag of current page.""" - def __init__(self, command: Callable, **kwargs: Any) -> None: + def __init__(self, command: Callable, **kwargs): super(ConfigurationSettingPropertiesPaged, self).__init__( self._get_next_cb, self._extract_data_cb, @@ -557,9 +557,8 @@ def __init__(self, command: Callable, **kwargs: Any) -> None: self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") self._cls = kwargs.get("cls") - - def _get_next_cb(self, continuation_token): # pylint: disable=inconsistent-return-statements + def _get_next_cb(self, continuation_token): response = self._command( key=self._key, label=self._label, @@ -568,10 +567,9 @@ def _get_next_cb(self, continuation_token): # pylint: disable=inconsistent-retu cls=self._cls, ).by_page(continuation_token=continuation_token) next(response) - self.page_etag = response._response.http_response.headers['Etag'] + self.etag = response._response.http_response.headers.get('Etag') return response - def _extract_data_cb(self, pipeline_response): return pipeline_response.continuation_token, pipeline_response._current_page @@ -579,10 +577,10 @@ def _extract_data_cb(self, pipeline_response): class ConfigurationSettingPropertiesPagedAsync(AsyncPageIterator): """An iterable of ConfigurationSetting properties.""" - page_etag: str + etag: str """The etag of current page.""" - def __init__(self, command: Callable, **kwargs: Any) -> None: + def __init__(self, command: Callable, **kwargs): super(ConfigurationSettingPropertiesPagedAsync, self).__init__( self._get_next_cb, self._extract_data_cb, @@ -594,9 +592,8 @@ def __init__(self, command: Callable, **kwargs: Any) -> None: self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") self._cls = kwargs.get("cls") - - async def _get_next_cb(self, continuation_token): # pylint: disable=inconsistent-return-statements + async def _get_next_cb(self, continuation_token): response = self._command( key=self._key, label=self._label, @@ -604,10 +601,9 @@ async def _get_next_cb(self, continuation_token): # pylint: disable=inconsisten select=self._select, cls=self._cls, ).by_page(continuation_token=continuation_token) - await anext(response) - self.page_etag = response._response.http_response.headers['Etag'] + await response.__anext__() + self.etag = response._response.http_response.headers.get('Etag') return response - async def _extract_data_cb(self, pipeline_response): return pipeline_response.continuation_token, pipeline_response._current_page diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py index d21248581103..c974ef432667 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py @@ -124,7 +124,7 @@ def from_connection_string(cls, connection_string: str, **kwargs: Any) -> "Azure ) @distributed_trace_async - async def send_request(self, request: HttpRequest, **kwargs) -> AsyncHttpResponse: + async def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs) -> AsyncHttpResponse: """Runs a network request using the client's existing pipeline. The request URL can be relative to the vault URL. The service API version used for the request is the same as @@ -134,13 +134,11 @@ async def send_request(self, request: HttpRequest, **kwargs) -> AsyncHttpRespons :param request: The network request you want to make. :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 """ - return await self._impl._send_request(request, **kwargs) + return await self._impl._send_request(request, stream=stream, **kwargs) @overload def list_configuration_settings( diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/send_request_sample.py b/sdk/appconfiguration/azure-appconfiguration/samples/send_request_sample.py new file mode 100644 index 000000000000..0593582adcd3 --- /dev/null +++ b/sdk/appconfiguration/azure-appconfiguration/samples/send_request_sample.py @@ -0,0 +1,38 @@ +# coding: utf-8 + +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- + +""" +FILE: sample_send_request.py + +DESCRIPTION: + This sample demonstrates how to make custom HTTP requests through a client pipeline. + +USAGE: + python sample_send_request.py + + Set the environment variables with your own values before running the sample: + 1) APPCONFIGURATION_CONNECTION_STRING: Connection String used to access the Azure App Configuration. +""" +import os +from azure.appconfiguration import AzureAppConfigurationClient +from azure.core.rest import HttpRequest + + +def main(): + CONNECTION_STRING = os.environ["APPCONFIGURATION_CONNECTION_STRING"] + with AzureAppConfigurationClient.from_connection_string(CONNECTION_STRING) as client: + request = HttpRequest( + method="GET", + url="/kv?api-version=2023-10-01", + ) + response = client.send_request(request) + print(response.status_code) + + +if __name__ == "__main__": + main() diff --git a/sdk/appconfiguration/azure-appconfiguration/samples/send_request_sample_async.py b/sdk/appconfiguration/azure-appconfiguration/samples/send_request_sample_async.py new file mode 100644 index 000000000000..9e3a4530fb40 --- /dev/null +++ b/sdk/appconfiguration/azure-appconfiguration/samples/send_request_sample_async.py @@ -0,0 +1,39 @@ +# coding: utf-8 + +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- + +""" +FILE: sample_send_request_async.py + +DESCRIPTION: + This sample demonstrates how to make custom HTTP requests through a client pipeline. + +USAGE: + python sample_send_request_async.py + + Set the environment variables with your own values before running the sample: + 1) APPCONFIGURATION_CONNECTION_STRING: Connection String used to access the Azure App Configuration. +""" +import os +import asyncio +from azure.appconfiguration.aio import AzureAppConfigurationClient +from azure.core.rest import HttpRequest + + +async def main(): + CONNECTION_STRING = os.environ["APPCONFIGURATION_CONNECTION_STRING"] + async with AzureAppConfigurationClient.from_connection_string(CONNECTION_STRING) as client: + request = HttpRequest( + method="GET", + url="/kv?api-version=2023-10-01", + ) + response = await client.send_request(request) + print(response.status_code) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py index 6289c41ddb97..ffb5c21951bf 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py @@ -1003,7 +1003,7 @@ def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_conn items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") iterator = items.by_page() for page in iterator: - etag = iterator.page_etag + etag = iterator.page page_etags.append(etag) # monitor page updates without changes @@ -1047,7 +1047,7 @@ def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_conn items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") iterator = items.by_page() for page in iterator: - etag = iterator.page_etag + etag = iterator.page new_page_etags.append(etag) assert page_etags[0] == new_page_etags[0] diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py index 63f4f2a314a7..4c2fd79c86d5 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py @@ -1025,7 +1025,7 @@ async def test_monitor_configuration_settings_by_page_etag(self, appconfiguratio items = client.list_configuration_settings(key_filter="async_sample_key_*", label_filter="async_sample_label_*") iterator = items.by_page() async for page in iterator: - etag = iterator.page_etag + etag = iterator.page page_etags.append(etag) # monitor page updates without changes @@ -1069,7 +1069,7 @@ async def test_monitor_configuration_settings_by_page_etag(self, appconfiguratio items = client.list_configuration_settings(key_filter="async_sample_key_*", label_filter="async_sample_label_*") iterator = items.by_page() async for page in iterator: - etag = iterator.page_etag + etag = iterator.page new_page_etags.append(etag) assert page_etags[0] == new_page_etags[0] From 7aa52677422924fb75cdf400164462dea6477bf6 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Fri, 8 Mar 2024 13:30:41 -0800 Subject: [PATCH 16/24] Address --- sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md | 2 +- .../tests/test_azure_appconfiguration_client.py | 4 ++-- .../tests/test_azure_appconfiguration_client_async.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md index 4c31c7806d14..52303a9f04ae 100644 --- a/sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md @@ -4,7 +4,7 @@ ### Features Added - Exposed `send_request()` method in each client to send custom requests using the client's existing pipeline. -- Supported to get `page_etag` while iterating `list_configuration_setting()` result by page. +- Supported to get page ETag while iterating `list_configuration_setting()` result by page. ### Bugs Fixed - Fixed a bug in consuming "etag" value in sync operation `set_configuration_setting()`. diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py index ffb5c21951bf..5e3a7ae66825 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py @@ -1003,7 +1003,7 @@ def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_conn items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") iterator = items.by_page() for page in iterator: - etag = iterator.page + etag = iterator.etag page_etags.append(etag) # monitor page updates without changes @@ -1047,7 +1047,7 @@ def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_conn items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") iterator = items.by_page() for page in iterator: - etag = iterator.page + etag = iterator.etag new_page_etags.append(etag) assert page_etags[0] == new_page_etags[0] diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py index 4c2fd79c86d5..90f0ff94a3d0 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py @@ -1025,7 +1025,7 @@ async def test_monitor_configuration_settings_by_page_etag(self, appconfiguratio items = client.list_configuration_settings(key_filter="async_sample_key_*", label_filter="async_sample_label_*") iterator = items.by_page() async for page in iterator: - etag = iterator.page + etag = iterator.etag page_etags.append(etag) # monitor page updates without changes @@ -1069,7 +1069,7 @@ async def test_monitor_configuration_settings_by_page_etag(self, appconfiguratio items = client.list_configuration_settings(key_filter="async_sample_key_*", label_filter="async_sample_label_*") iterator = items.by_page() async for page in iterator: - etag = iterator.page + etag = iterator.etag new_page_etags.append(etag) assert page_etags[0] == new_page_etags[0] From 7ec5960bbf3a35a98d4ba002acf21690e9f1c4ce Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Tue, 12 Mar 2024 19:06:37 -0700 Subject: [PATCH 17/24] Changed to call patch ops --- .../_azure_appconfiguration_client.py | 7 +- .../_generated/aio/operations/_patch.py | 149 ++++++++++++++++- .../_generated/operations/_patch.py | 153 +++++++++++++++++- .../azure/appconfiguration/_models.py | 31 ++-- .../_azure_appconfiguration_client_async.py | 5 +- 5 files changed, 323 insertions(+), 22 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py index c8b0523f1627..0055e5db07ec 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py @@ -41,6 +41,9 @@ ) from ._sync_token import SyncTokenPolicy +def _return_deserialized_and_headers(response, deserialized, response_headers): + return deserialized, response_headers + class AzureAppConfigurationClient: """Represents a client that calls restful API of Azure App Configuration service. @@ -218,14 +221,14 @@ def list_configuration_settings( ) key_filter, kwargs = get_key_filter(*args, **kwargs) label_filter, kwargs = get_label_filter(*args, **kwargs) - command = functools.partial(self._impl.get_key_values, **kwargs) + command = functools.partial(self._impl.get_key_values_in_one_page, **kwargs) return ItemPaged( command, key=key_filter, label=label_filter, accept_datetime=accept_datetime, select=select, - cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs], + cls=_return_deserialized_and_headers, page_iterator_class=ConfigurationSettingPropertiesPaged, ) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/aio/operations/_patch.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/aio/operations/_patch.py index f7dd32510333..bebc16a9a44d 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/aio/operations/_patch.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/aio/operations/_patch.py @@ -6,9 +6,154 @@ Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ -from typing import List +import urllib.parse +from typing import Any, AsyncIterable, List, Optional, Union +from azure.core.exceptions import ( + ClientAuthenticationError, + HttpResponseError, + ResourceExistsError, + ResourceNotFoundError, + ResourceNotModifiedError, + map_error, +) +from azure.core.rest import HttpRequest +from azure.core.tracing.decorator_async import distributed_trace_async +from azure.core.utils import case_insensitive_dict +from ._azure_app_configuration_operations import ( + AzureAppConfigurationOperationsMixin as AzureAppConfigOpGenerated, + ClsType, + build_get_key_values_request, +) +from ... import models as _models +from ..._vendor import _convert_request -__all__: List[str] = [] # Add all objects you want publicly available to users at this package level + +class AzureAppConfigurationOperationsMixin(AzureAppConfigOpGenerated): + @distributed_trace_async + async def get_key_values_in_one_page( + self, + key: Optional[str] = None, + label: Optional[str] = None, + after: Optional[str] = None, + accept_datetime: Optional[str] = None, + select: Optional[List[Union[str, _models.KeyValueFields]]] = None, + if_match: Optional[str] = None, + if_none_match: Optional[str] = None, + continuation_token: Optional[str] = None, + **kwargs: Any + ) -> AsyncIterable["_models.KeyValue"]: + """Gets a list of key-values in one page. + + Gets a list of key-values in one page. + + :param key: A filter used to match keys. Default value is None. + :type key: str + :param label: A filter used to match labels. Default value is None. + :type label: str + :param after: Instructs the server to return elements that appear after the element referred to + by the specified token. Default value is None. + :type after: str + :param accept_datetime: Requests the server to respond with the state of the resource at the + specified time. Default value is None. + :type accept_datetime: str + :param select: Used to select what fields are present in the returned resource(s). Default + value is None. + :type select: list[str or ~azure.appconfiguration.models.KeyValueFields] + :param if_match: Used to perform an operation only if the targeted resource's etag matches the + value provided. Default value is None. + :type if_match: str + :param if_none_match: Used to perform an operation only if the targeted resource's etag does + not match the value provided. Default value is None. + :type if_none_match: str + :param str continuation_token: An opaque continuation token. + :keyword callable cls: A custom type or function that will be passed the direct response + :return: An iterator like instance of either KeyValue or the result of cls(response) + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.appconfiguration.models.KeyValue] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version)) + cls: ClsType[_models.KeyValueListResult] = kwargs.pop("cls", None) + + error_map = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_get_key_values_request( + key=key, + label=label, + after=after, + accept_datetime=accept_datetime, + select=select, + if_match=if_match, + if_none_match=if_none_match, + sync_token=self._config.sync_token, + api_version=api_version, + headers=_headers, + params=_params, + ) + _request = _convert_request(_request) + 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) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params + ) + _request = _convert_request(_request) + 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) + _request.method = "GET" + return _request + + _request = prepare_request(continuation_token) + + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **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) + error = self._deserialize.failsafe_deserialize(_models.Error, pipeline_response) + raise HttpResponseError(response=response, model=error) + + response_headers = response.headers + deserialized = self._deserialize("KeyValueListResult", pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, response_headers) + + return deserialized + +__all__: List[str] = ["AzureAppConfigurationOperationsMixin"] # Add all objects you want publicly available to users at this package level def patch_sdk(): diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py index f7dd32510333..fa1f0028d87e 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py @@ -6,9 +6,158 @@ Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ -from typing import List +import urllib.parse +from typing import Any, Iterable, List, Optional, Union +from azure.core.exceptions import ( + ClientAuthenticationError, + HttpResponseError, + ResourceExistsError, + ResourceNotFoundError, + ResourceNotModifiedError, + map_error, +) +from azure.core.pipeline import PipelineResponse +from azure.core.rest import HttpRequest +from azure.core.tracing.decorator import distributed_trace +from azure.core.utils import case_insensitive_dict +from ._azure_app_configuration_operations import ( + AzureAppConfigurationOperationsMixin as AzureAppConfigOpGenerated, + ClsType, + build_get_key_values_request, +) +from .. import models as _models +from .._vendor import _convert_request -__all__: List[str] = [] # Add all objects you want publicly available to users at this package level + +class AzureAppConfigurationOperationsMixin(AzureAppConfigOpGenerated): + @distributed_trace + def get_key_values_in_one_page( + self, + key: Optional[str] = None, + label: Optional[str] = None, + after: Optional[str] = None, + accept_datetime: Optional[str] = None, + select: Optional[List[Union[str, _models.KeyValueFields]]] = None, + if_match: Optional[str] = None, + if_none_match: Optional[str] = None, + continuation_token: Optional[str] = None, + **kwargs: Any + ) -> Iterable["_models.KeyValue"]: + """Gets a list of key-values in one page. + + Gets a list of key-values in one page. + + :param key: A filter used to match keys. Default value is None. + :type key: str + :param label: A filter used to match labels. Default value is None. + :type label: str + :param after: Instructs the server to return elements that appear after the element referred to + by the specified token. Default value is None. + :type after: str + :param accept_datetime: Requests the server to respond with the state of the resource at the + specified time. Default value is None. + :type accept_datetime: str + :param select: Used to select what fields are present in the returned resource(s). Default + value is None. + :type select: list[str or ~azure.appconfiguration.models.KeyValueFields] + :param snapshot: A filter used get key-values for a snapshot. The value should be the name of + the snapshot. Not valid when used with 'key' and 'label' filters. Default value is None. + :type snapshot: str + :param if_match: Used to perform an operation only if the targeted resource's etag matches the + value provided. Default value is None. + :type if_match: str + :param if_none_match: Used to perform an operation only if the targeted resource's etag does + not match the value provided. Default value is None. + :type if_none_match: str + :param str continuation_token: An opaque continuation token. + :keyword callable cls: A custom type or function that will be passed the direct response + :return: An iterator like instance of either KeyValue or the result of cls(response) + :rtype: ~azure.core.paging.ItemPaged[~azure.appconfiguration.models.KeyValue] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version)) + cls: ClsType[_models.KeyValueListResult] = kwargs.pop("cls", None) + + error_map = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_get_key_values_request( + key=key, + label=label, + after=after, + accept_datetime=accept_datetime, + select=select, + if_match=if_match, + if_none_match=if_none_match, + sync_token=self._config.sync_token, + api_version=api_version, + headers=_headers, + params=_params, + ) + _request = _convert_request(_request) + 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) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params + ) + _request = _convert_request(_request) + 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) + _request.method = "GET" + return _request + + _request = prepare_request(continuation_token) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.Error, pipeline_response) + raise HttpResponseError(response=response, model=error) + + response_headers = response.headers + deserialized = self._deserialize("KeyValueListResult", pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, response_headers) + + return deserialized + +__all__: List[str] = ["AzureAppConfigurationOperationsMixin"] # Add all objects you want publicly available to users at this package level def patch_sdk(): diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py index 36dc0c4fc20f..27409f8a6660 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py @@ -7,6 +7,7 @@ from typing import Any, Dict, List, Optional, Union, cast, Callable from typing_extensions import Literal +from azure.core.async_paging import AsyncList from azure.core.rest import HttpResponse from azure.core.paging import PageIterator from azure.core.async_paging import AsyncPageIterator @@ -557,21 +558,22 @@ def __init__(self, command: Callable, **kwargs): self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") self._cls = kwargs.get("cls") + self._deserializer = lambda objs: [ConfigurationSetting._from_generated(x) for x in objs] def _get_next_cb(self, continuation_token): - response = self._command( + return self._command( key=self._key, label=self._label, accept_datetime=self._accept_datetime, select=self._select, + continuation_token=continuation_token, cls=self._cls, - ).by_page(continuation_token=continuation_token) - next(response) - self.etag = response._response.http_response.headers.get('Etag') - return response + ) - def _extract_data_cb(self, pipeline_response): - return pipeline_response.continuation_token, pipeline_response._current_page + def _extract_data_cb(self, get_next_return): + deserialized, response_headers = get_next_return + self.etag = response_headers.get('ETag') + return deserialized.next_link or None, iter(self._deserializer(deserialized.items)) class ConfigurationSettingPropertiesPagedAsync(AsyncPageIterator): @@ -592,18 +594,19 @@ def __init__(self, command: Callable, **kwargs): self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") self._cls = kwargs.get("cls") + self._deserializer = lambda objs: [ConfigurationSetting._from_generated(x) for x in objs] async def _get_next_cb(self, continuation_token): - response = self._command( + return await self._command( key=self._key, label=self._label, accept_datetime=self._accept_datetime, select=self._select, + continuation_token=continuation_token, cls=self._cls, - ).by_page(continuation_token=continuation_token) - await response.__anext__() - self.etag = response._response.http_response.headers.get('Etag') - return response + ) - async def _extract_data_cb(self, pipeline_response): - return pipeline_response.continuation_token, pipeline_response._current_page + async def _extract_data_cb(self, get_next_return): + deserialized, response_headers = get_next_return + self.etag = response_headers.get('ETag') + return deserialized.next_link or None, AsyncList(self._deserializer(deserialized.items)) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py index c974ef432667..944539773e0b 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py @@ -25,6 +25,7 @@ from azure.core.rest import AsyncHttpResponse, HttpRequest from azure.core.utils import CaseInsensitiveDict from ._sync_token_async import AsyncSyncTokenPolicy +from .._azure_appconfiguration_client import _return_deserialized_and_headers from .._azure_appconfiguration_error import ResourceReadOnlyError from .._azure_appconfiguration_requests import AppConfigRequestsCredentialsPolicy from .._generated.aio import AzureAppConfiguration @@ -224,14 +225,14 @@ def list_configuration_settings(self, *args, **kwargs) -> AsyncItemPaged[Configu ) key_filter, kwargs = get_key_filter(*args, **kwargs) label_filter, kwargs = get_label_filter(*args, **kwargs) - command = functools.partial(self._impl.get_key_values, **kwargs) + command = functools.partial(self._impl.get_key_values_in_one_page, **kwargs) return AsyncItemPaged( command, key=key_filter, label=label_filter, accept_datetime=accept_datetime, select=select, - cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs], + cls=_return_deserialized_and_headers, page_iterator_class=ConfigurationSettingPropertiesPagedAsync, ) except binascii.Error as exc: From db1661ad42d1f2d2527aaa6fb4e86f4f190877c6 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 14 Mar 2024 15:29:44 -0700 Subject: [PATCH 18/24] Update version and releasing date --- sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md | 2 +- .../azure-appconfiguration/azure/appconfiguration/_version.py | 2 +- sdk/appconfiguration/azure-appconfiguration/setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md index 52303a9f04ae..a38989485545 100644 --- a/sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 1.5.1 (2024-03-07) +## 1.6.0b1 (2024-03-14) ### Features Added - Exposed `send_request()` method in each client to send custom requests using the client's existing pipeline. diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_version.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_version.py index 26faba9eba0c..7af12c9a4dd9 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_version.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_version.py @@ -3,4 +3,4 @@ # Licensed under the MIT License. # ------------------------------------ -VERSION = "1.5.1" +VERSION = "1.6.0b1" diff --git a/sdk/appconfiguration/azure-appconfiguration/setup.py b/sdk/appconfiguration/azure-appconfiguration/setup.py index eaa5aebaf03c..1d7607c4c958 100644 --- a/sdk/appconfiguration/azure-appconfiguration/setup.py +++ b/sdk/appconfiguration/azure-appconfiguration/setup.py @@ -53,7 +53,7 @@ url="https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/appconfiguration/azure-appconfiguration", keywords="azure, azure sdk", classifiers=[ - "Development Status :: 5 - Production/Stable", + "Development Status :: 4 - Beta", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3", From 08693791b21bfff9d1a49ae21114eefa272814cb Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 14 Mar 2024 18:03:18 -0700 Subject: [PATCH 19/24] Ignore missing headers in py38 --- .../test_azure_appconfiguration_client.py | 82 ++++++++++++++++++- .../test_azure_appconfiguration_client_aad.py | 58 ++++++++++++- ...azure_appconfiguration_client_aad_async.py | 53 ++++++++++++ ...est_azure_appconfiguration_client_async.py | 81 ++++++++++++++++++ .../tests/test_consistency.py | 18 +++- 5 files changed, 289 insertions(+), 3 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py index 5e3a7ae66825..88b40700580d 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py @@ -39,7 +39,7 @@ ) from uuid import uuid4 from preparers import app_config_decorator -from devtools_testutils import recorded_by_proxy +from devtools_testutils import recorded_by_proxy, set_custom_default_matcher class TestAppConfigurationClient(AppConfigTestCase): @@ -222,6 +222,10 @@ def test_delete_configuration_setting_with_etag(self, appconfiguration_connectio @app_config_decorator @recorded_by_proxy def test_list_configuration_settings_key_label(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) items = list(self.client.list_configuration_settings(KEY, LABEL)) assert len(items) == 1 @@ -257,6 +261,10 @@ def test_list_configuration_settings_key_label(self, appconfiguration_connection @app_config_decorator @recorded_by_proxy def test_list_configuration_settings_only_label(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) items = list(self.client.list_configuration_settings(label_filter=LABEL)) assert len(items) == 1 @@ -266,6 +274,10 @@ def test_list_configuration_settings_only_label(self, appconfiguration_connectio @app_config_decorator @recorded_by_proxy def test_list_configuration_settings_only_key(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) items = list(self.client.list_configuration_settings(KEY)) assert len(items) == 2 @@ -275,6 +287,10 @@ def test_list_configuration_settings_only_key(self, appconfiguration_connection_ @app_config_decorator @recorded_by_proxy def test_list_configuration_settings_fields(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) items = list( self.client.list_configuration_settings(key_filter="*", label_filter=LABEL, fields=["key", "content_type"]) @@ -286,6 +302,10 @@ def test_list_configuration_settings_fields(self, appconfiguration_connection_st @app_config_decorator @recorded_by_proxy def test_list_configuration_settings_reserved_chars(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) client = self.create_client(appconfiguration_connection_string) reserved_char_kv = ConfigurationSetting(key=KEY, label=LABEL_RESERVED_CHARS, value=TEST_VALUE) reserved_char_kv = client.add_configuration_setting(reserved_char_kv) @@ -298,6 +318,10 @@ def test_list_configuration_settings_reserved_chars(self, appconfiguration_conne @app_config_decorator @recorded_by_proxy def test_list_configuration_settings_contains(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) items = list(self.client.list_configuration_settings(label_filter=LABEL + "*")) assert len(items) == 1 @@ -307,6 +331,10 @@ def test_list_configuration_settings_contains(self, appconfiguration_connection_ @app_config_decorator @recorded_by_proxy def test_list_configuration_settings_correct_etag(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) client = self.create_client(appconfiguration_connection_string) to_list_kv = self.create_config_setting() self.add_for_test(client, to_list_kv) @@ -324,6 +352,10 @@ def test_list_configuration_settings_correct_etag(self, appconfiguration_connect @app_config_decorator @recorded_by_proxy def test_list_configuration_settings_multi_pages(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) client = self.create_client(appconfiguration_connection_string) # create PAGE_SIZE+1 configuration settings to have at least two pages try: @@ -354,6 +386,10 @@ def test_list_configuration_settings_multi_pages(self, appconfiguration_connecti @app_config_decorator @recorded_by_proxy def test_list_configuration_settings_no_label(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) items = self.client.list_configuration_settings(label_filter="\0") assert len(list(items)) > 0 @@ -362,6 +398,10 @@ def test_list_configuration_settings_no_label(self, appconfiguration_connection_ @app_config_decorator @recorded_by_proxy def test_list_configuration_settings_only_accepttime(self, appconfiguration_connection_string, **kwargs): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) recorded_variables = kwargs.pop("variables", {}) recorded_variables.setdefault("timestamp", str(datetime.utcnow())) @@ -385,6 +425,10 @@ def test_list_configuration_settings_only_accepttime(self, appconfiguration_conn @app_config_decorator @recorded_by_proxy def test_list_revisions_key_label(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) to_list1 = self.create_config_setting() items = list(self.client.list_revisions(label_filter=to_list1.label, key_filter=to_list1.key)) @@ -395,6 +439,10 @@ def test_list_revisions_key_label(self, appconfiguration_connection_string): @app_config_decorator @recorded_by_proxy def test_list_revisions_only_label(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) items = list(self.client.list_revisions(label_filter=LABEL)) assert len(items) >= 1 @@ -404,6 +452,10 @@ def test_list_revisions_only_label(self, appconfiguration_connection_string): @app_config_decorator @recorded_by_proxy def test_list_revisions_key_no_label(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) items = list(self.client.list_revisions(key_filter=KEY)) assert len(items) >= 1 @@ -413,6 +465,10 @@ def test_list_revisions_key_no_label(self, appconfiguration_connection_string): @app_config_decorator @recorded_by_proxy def test_list_revisions_fields(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) items = list(self.client.list_revisions(key_filter="*", label_filter=LABEL, fields=["key", "content_type"])) assert all(x.key and not x.label and x.content_type and not x.tags and not x.etag for x in items) @@ -891,6 +947,10 @@ def test_breaking_with_secret_reference_configuration_setting(self, appconfigura @app_config_decorator @recorded_by_proxy def test_create_snapshot(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -910,6 +970,10 @@ def test_create_snapshot(self, appconfiguration_connection_string): @app_config_decorator @recorded_by_proxy def test_update_snapshot_status(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -928,6 +992,10 @@ def test_update_snapshot_status(self, appconfiguration_connection_string): @app_config_decorator @recorded_by_proxy def test_update_snapshot_status_with_etag(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -948,6 +1016,10 @@ def test_update_snapshot_status_with_etag(self, appconfiguration_connection_stri @app_config_decorator @recorded_by_proxy def test_list_snapshots(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) result = self.client.list_snapshots() @@ -972,6 +1044,10 @@ def test_list_snapshots(self, appconfiguration_connection_string): @app_config_decorator @recorded_by_proxy def test_list_snapshot_configuration_settings(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -987,6 +1063,10 @@ def test_list_snapshot_configuration_settings(self, appconfiguration_connection_ @app_config_decorator @recorded_by_proxy def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) with AzureAppConfigurationClient.from_connection_string(appconfiguration_connection_string) as client: # prepare 200 configuration settings for i in range(200): diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad.py index 98e902c7a7b3..982b25ca8e17 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad.py @@ -30,7 +30,7 @@ KEY_UUID, ) from preparers import app_config_aad_decorator -from devtools_testutils import recorded_by_proxy +from devtools_testutils import recorded_by_proxy, set_custom_default_matcher import pytest import copy import datetime @@ -202,6 +202,10 @@ def test_delete_configuration_setting_with_etag(self, appconfiguration_endpoint_ @app_config_aad_decorator @recorded_by_proxy def test_list_configuration_settings_key_label(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_configuration_settings(label_filter=LABEL, key_filter=KEY)) assert len(items) == 1 @@ -211,6 +215,10 @@ def test_list_configuration_settings_key_label(self, appconfiguration_endpoint_s @app_config_aad_decorator @recorded_by_proxy def test_list_configuration_settings_only_label(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_configuration_settings(label_filter=LABEL)) assert len(items) == 1 @@ -220,6 +228,10 @@ def test_list_configuration_settings_only_label(self, appconfiguration_endpoint_ @app_config_aad_decorator @recorded_by_proxy def test_list_configuration_settings_only_key(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_configuration_settings(key_filter=KEY)) assert len(items) == 2 @@ -229,6 +241,10 @@ def test_list_configuration_settings_only_key(self, appconfiguration_endpoint_st @app_config_aad_decorator @recorded_by_proxy def test_list_configuration_settings_fields(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list( self.client.list_configuration_settings(key_filter="*", label_filter=LABEL, fields=["key", "content_type"]) @@ -240,6 +256,10 @@ def test_list_configuration_settings_fields(self, appconfiguration_endpoint_stri @app_config_aad_decorator @recorded_by_proxy def test_list_configuration_settings_reserved_chars(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) client = self.create_aad_client(appconfiguration_endpoint_string) reserved_char_kv = ConfigurationSetting(key=KEY, label=LABEL_RESERVED_CHARS, value=TEST_VALUE) reserved_char_kv = client.add_configuration_setting(reserved_char_kv) @@ -252,6 +272,10 @@ def test_list_configuration_settings_reserved_chars(self, appconfiguration_endpo @app_config_aad_decorator @recorded_by_proxy def test_list_configuration_settings_contains(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_configuration_settings(label_filter=LABEL + "*")) assert len(items) == 1 @@ -261,6 +285,10 @@ def test_list_configuration_settings_contains(self, appconfiguration_endpoint_st @app_config_aad_decorator @recorded_by_proxy def test_list_configuration_settings_correct_etag(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) client = self.create_aad_client(appconfiguration_endpoint_string) to_list_kv = self.create_config_setting() self.add_for_test(client, to_list_kv) @@ -278,6 +306,10 @@ def test_list_configuration_settings_correct_etag(self, appconfiguration_endpoin @app_config_aad_decorator @recorded_by_proxy def test_list_configuration_settings_multi_pages(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) client = self.create_aad_client(appconfiguration_endpoint_string) # create PAGE_SIZE+1 configuration settings to have at least two pages try: @@ -308,6 +340,10 @@ def test_list_configuration_settings_multi_pages(self, appconfiguration_endpoint @app_config_aad_decorator @recorded_by_proxy def test_list_configuration_settings_no_label(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_endpoint_string, is_aad=True) items = self.client.list_configuration_settings(label_filter="\0") assert len(list(items)) > 0 @@ -316,6 +352,10 @@ def test_list_configuration_settings_no_label(self, appconfiguration_endpoint_st @app_config_aad_decorator @recorded_by_proxy def test_list_configuration_settings_only_accepttime(self, appconfiguration_endpoint_string, **kwargs): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) recorded_variables = kwargs.pop("variables", {}) self.set_up(appconfiguration_endpoint_string, is_aad=True) exclude_today = self.client.list_configuration_settings( @@ -332,6 +372,10 @@ def test_list_configuration_settings_only_accepttime(self, appconfiguration_endp @app_config_aad_decorator @recorded_by_proxy def test_list_revisions_key_label(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_endpoint_string, is_aad=True) to_list = self.create_config_setting() items = list(self.client.list_revisions(label_filter=to_list.label, key_filter=to_list.key)) @@ -342,6 +386,10 @@ def test_list_revisions_key_label(self, appconfiguration_endpoint_string): @app_config_aad_decorator @recorded_by_proxy def test_list_revisions_only_label(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_revisions(label_filter=LABEL)) assert len(items) >= 1 @@ -351,6 +399,10 @@ def test_list_revisions_only_label(self, appconfiguration_endpoint_string): @app_config_aad_decorator @recorded_by_proxy def test_list_revisions_key_no_label(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_revisions(key_filter=KEY)) assert len(items) >= 1 @@ -360,6 +412,10 @@ def test_list_revisions_key_no_label(self, appconfiguration_endpoint_string): @app_config_aad_decorator @recorded_by_proxy def test_list_revisions_fields(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_revisions(key_filter="*", label_filter=LABEL, fields=["key", "content_type"])) assert all(x.key and not x.label and x.content_type and not x.tags and not x.etag for x in items) diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad_async.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad_async.py index b9ba06d9b59b..1b21eb29aa46 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad_async.py @@ -30,6 +30,7 @@ KEY_UUID, ) from async_preparers import app_config_aad_decorator_async +from devtools_testutils import set_custom_default_matcher from devtools_testutils.aio import recorded_by_proxy_async import pytest import copy @@ -219,6 +220,10 @@ async def test_delete_configuration_setting_with_etag(self, appconfiguration_end @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_key_label(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list(self.client.list_configuration_settings(label_filter=LABEL, key_filter=KEY)) assert len(items) == 1 @@ -228,6 +233,10 @@ async def test_list_configuration_settings_key_label(self, appconfiguration_endp @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_only_label(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list(self.client.list_configuration_settings(label_filter=LABEL)) assert len(items) == 1 @@ -237,6 +246,10 @@ async def test_list_configuration_settings_only_label(self, appconfiguration_end @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_only_key(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list(self.client.list_configuration_settings(key_filter=KEY)) assert len(items) == 2 @@ -246,6 +259,10 @@ async def test_list_configuration_settings_only_key(self, appconfiguration_endpo @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_fields(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list( self.client.list_configuration_settings(key_filter="*", label_filter=LABEL, fields=["key", "content_type"]) @@ -257,6 +274,10 @@ async def test_list_configuration_settings_fields(self, appconfiguration_endpoin @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_reserved_chars(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) async with self.create_aad_client(appconfiguration_endpoint_string) as client: reserved_char_kv = ConfigurationSetting(key=KEY, label=LABEL_RESERVED_CHARS, value=TEST_VALUE) reserved_char_kv = await client.add_configuration_setting(reserved_char_kv) @@ -270,6 +291,10 @@ async def test_list_configuration_settings_reserved_chars(self, appconfiguration @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_contains(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list(self.client.list_configuration_settings(label_filter=LABEL + "*")) assert len(items) == 1 @@ -279,6 +304,10 @@ async def test_list_configuration_settings_contains(self, appconfiguration_endpo @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_correct_etag(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) async with self.create_aad_client(appconfiguration_endpoint_string) as client: to_list_kv = self.create_config_setting() await self.add_for_test(client, to_list_kv) @@ -296,6 +325,10 @@ async def test_list_configuration_settings_correct_etag(self, appconfiguration_e @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_multi_pages(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) async with self.create_aad_client(appconfiguration_endpoint_string) as client: # create PAGE_SIZE+1 configuration settings to have at least two pages try: @@ -336,6 +369,10 @@ async def test_list_configuration_settings_null_label(self, appconfiguration_end @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_only_accepttime(self, appconfiguration_endpoint_string, **kwargs): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) recorded_variables = kwargs.pop("variables", {}) await self.set_up(appconfiguration_endpoint_string, is_aad=True) exclude_today = await self.convert_to_list( @@ -354,6 +391,10 @@ async def test_list_configuration_settings_only_accepttime(self, appconfiguratio @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_revisions_key_label(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_endpoint_string, is_aad=True) to_list = self.create_config_setting() items = await self.convert_to_list( @@ -366,6 +407,10 @@ async def test_list_revisions_key_label(self, appconfiguration_endpoint_string): @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_revisions_only_label(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list(self.client.list_revisions(label_filter=LABEL)) assert len(items) >= 1 @@ -375,6 +420,10 @@ async def test_list_revisions_only_label(self, appconfiguration_endpoint_string) @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_revisions_key_no_label(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list(self.client.list_revisions(key_filter=KEY)) assert len(items) >= 1 @@ -384,6 +433,10 @@ async def test_list_revisions_key_no_label(self, appconfiguration_endpoint_strin @app_config_aad_decorator_async @recorded_by_proxy_async async def test_list_revisions_fields(self, appconfiguration_endpoint_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list( self.client.list_revisions(key_filter="*", label_filter=LABEL, fields=["key", "content_type"]) diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py index 90f0ff94a3d0..3b56436348cb 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py @@ -37,6 +37,7 @@ PAGE_SIZE, KEY_UUID, ) +from devtools_testutils import set_custom_default_matcher from devtools_testutils.aio import recorded_by_proxy_async from async_preparers import app_config_decorator_async from uuid import uuid4 @@ -222,6 +223,10 @@ async def test_delete_configuration_setting_with_etag(self, appconfiguration_con @app_config_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_key_label(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_configuration_settings(KEY, LABEL)) assert len(items) == 1 @@ -257,6 +262,10 @@ async def test_list_configuration_settings_key_label(self, appconfiguration_conn @app_config_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_only_label(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_configuration_settings(label_filter=LABEL)) assert len(items) == 1 @@ -266,6 +275,10 @@ async def test_list_configuration_settings_only_label(self, appconfiguration_con @app_config_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_only_key(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_configuration_settings(KEY)) assert len(items) == 2 @@ -275,6 +288,10 @@ async def test_list_configuration_settings_only_key(self, appconfiguration_conne @app_config_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_fields(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list( self.client.list_configuration_settings(key_filter="*", label_filter=LABEL, fields=["key", "content_type"]) @@ -286,6 +303,10 @@ async def test_list_configuration_settings_fields(self, appconfiguration_connect @app_config_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_reserved_chars(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) async with self.create_client(appconfiguration_connection_string) as client: reserved_char_kv = ConfigurationSetting(key=KEY, label=LABEL_RESERVED_CHARS, value=TEST_VALUE) reserved_char_kv = await client.add_configuration_setting(reserved_char_kv) @@ -298,6 +319,10 @@ async def test_list_configuration_settings_reserved_chars(self, appconfiguration @app_config_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_contains(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_configuration_settings(label_filter=LABEL + "*")) assert len(items) == 1 @@ -307,6 +332,10 @@ async def test_list_configuration_settings_contains(self, appconfiguration_conne @app_config_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_correct_etag(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) async with self.create_client(appconfiguration_connection_string) as client: to_list_kv = self.create_config_setting() await self.add_for_test(client, to_list_kv) @@ -324,6 +353,10 @@ async def test_list_configuration_settings_correct_etag(self, appconfiguration_c @app_config_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_multi_pages(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) async with self.create_client(appconfiguration_connection_string) as client: # create PAGE_SIZE+1 configuration settings to have at least two pages try: @@ -356,6 +389,10 @@ async def test_list_configuration_settings_multi_pages(self, appconfiguration_co @app_config_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_no_label(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_configuration_settings(label_filter="\0")) assert len(items) > 0 @@ -364,6 +401,10 @@ async def test_list_configuration_settings_no_label(self, appconfiguration_conne @app_config_decorator_async @recorded_by_proxy_async async def test_list_configuration_settings_only_accepttime(self, appconfiguration_connection_string, **kwargs): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) recorded_variables = kwargs.pop("variables", {}) recorded_variables.setdefault("timestamp", str(datetime.utcnow())) @@ -389,6 +430,10 @@ async def test_list_configuration_settings_only_accepttime(self, appconfiguratio @app_config_decorator_async @recorded_by_proxy_async async def test_list_revisions_key_label(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) to_list1 = self.create_config_setting() items = await self.convert_to_list( @@ -401,6 +446,10 @@ async def test_list_revisions_key_label(self, appconfiguration_connection_string @app_config_decorator_async @recorded_by_proxy_async async def test_list_revisions_only_label(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_revisions(label_filter=LABEL)) assert len(items) >= 1 @@ -410,6 +459,10 @@ async def test_list_revisions_only_label(self, appconfiguration_connection_strin @app_config_decorator_async @recorded_by_proxy_async async def test_list_revisions_key_no_label(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_revisions(key_filter=KEY)) assert len(items) >= 1 @@ -419,6 +472,10 @@ async def test_list_revisions_key_no_label(self, appconfiguration_connection_str @app_config_decorator_async @recorded_by_proxy_async async def test_list_revisions_fields(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list( self.client.list_revisions(key_filter="*", label_filter=LABEL, fields=["key", "content_type"]) @@ -913,6 +970,10 @@ async def test_breaking_with_secret_reference_configuration_setting(self, appcon @app_config_decorator_async @recorded_by_proxy_async async def test_create_snapshot(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -932,6 +993,10 @@ async def test_create_snapshot(self, appconfiguration_connection_string): @app_config_decorator_async @recorded_by_proxy_async async def test_update_snapshot_status(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -950,6 +1015,10 @@ async def test_update_snapshot_status(self, appconfiguration_connection_string): @app_config_decorator_async @recorded_by_proxy_async async def test_update_snapshot_status_with_etag(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -970,6 +1039,10 @@ async def test_update_snapshot_status_with_etag(self, appconfiguration_connectio @app_config_decorator_async @recorded_by_proxy_async async def test_list_snapshots(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) result = await self.convert_to_list(self.client.list_snapshots()) @@ -994,6 +1067,10 @@ async def test_list_snapshots(self, appconfiguration_connection_string): @app_config_decorator_async @recorded_by_proxy_async async def test_list_snapshot_configuration_settings(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) await self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -1009,6 +1086,10 @@ async def test_list_snapshot_configuration_settings(self, appconfiguration_conne @app_config_decorator_async @recorded_by_proxy_async async def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) async with AzureAppConfigurationClient.from_connection_string(appconfiguration_connection_string) as client: # prepare 200 configuration settings for i in range(200): diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_consistency.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_consistency.py index c60bd9f4ffdf..ad4405d37cf2 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_consistency.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_consistency.py @@ -9,7 +9,7 @@ ) from testcase import AppConfigTestCase from preparers import app_config_decorator -from devtools_testutils import recorded_by_proxy +from devtools_testutils import recorded_by_proxy, set_custom_default_matcher import json import pytest @@ -18,6 +18,10 @@ class TestAppConfigurationConsistency(AppConfigTestCase): @app_config_decorator @recorded_by_proxy def test_update_json_by_value(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) client = self.create_client(appconfiguration_connection_string) key = self.get_resource_name("key") feature_flag = FeatureFlagConfigurationSetting( @@ -54,6 +58,10 @@ def test_update_json_by_value(self, appconfiguration_connection_string): @app_config_decorator @recorded_by_proxy def test_feature_flag_invalid_json(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) client = self.create_client(appconfiguration_connection_string) key = self.get_resource_name("key") feature_flag = FeatureFlagConfigurationSetting(key, enabled=True) @@ -68,6 +76,10 @@ def test_feature_flag_invalid_json(self, appconfiguration_connection_string): @app_config_decorator @recorded_by_proxy def test_feature_flag_invalid_json_string(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) client = self.create_client(appconfiguration_connection_string) key = self.get_resource_name("key") feature_flag = FeatureFlagConfigurationSetting(key, enabled=True) @@ -82,6 +94,10 @@ def test_feature_flag_invalid_json_string(self, appconfiguration_connection_stri @app_config_decorator @recorded_by_proxy def test_feature_flag_invalid_json_access_properties(self, appconfiguration_connection_string): + # response header and are missing in python38. + set_custom_default_matcher( + compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" + ) client = self.create_client(appconfiguration_connection_string) key = self.get_resource_name("key") feature_flag = FeatureFlagConfigurationSetting(key, enabled=True) From f3c999264e9459a963a46572e7f3a709ea8c6e15 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 14 Mar 2024 18:04:09 -0700 Subject: [PATCH 20/24] Fix multiple values for 'cls' --- .../_azure_appconfiguration_client.py | 4 ---- .../azure/appconfiguration/_models.py | 14 ++++++++------ .../aio/_azure_appconfiguration_client_async.py | 2 -- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py index 0055e5db07ec..957b9c63711a 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py @@ -41,9 +41,6 @@ ) from ._sync_token import SyncTokenPolicy -def _return_deserialized_and_headers(response, deserialized, response_headers): - return deserialized, response_headers - class AzureAppConfigurationClient: """Represents a client that calls restful API of Azure App Configuration service. @@ -228,7 +225,6 @@ def list_configuration_settings( label=label_filter, accept_datetime=accept_datetime, select=select, - cls=_return_deserialized_and_headers, page_iterator_class=ConfigurationSettingPropertiesPaged, ) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py index 27409f8a6660..3db067ad1dc5 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py @@ -540,6 +540,10 @@ def _to_generated(self) -> GeneratedConfigurationSnapshot: ) +def _return_deserialized_and_headers(response, deserialized, response_headers): + return deserialized, response_headers + + class ConfigurationSettingPropertiesPaged(PageIterator): """An iterable of ConfigurationSetting properties.""" @@ -557,17 +561,16 @@ def __init__(self, command: Callable, **kwargs): self._label = kwargs.get("label") self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") - self._cls = kwargs.get("cls") self._deserializer = lambda objs: [ConfigurationSetting._from_generated(x) for x in objs] - def _get_next_cb(self, continuation_token): + def _get_next_cb(self, continuation_token, **kwargs): return self._command( key=self._key, label=self._label, accept_datetime=self._accept_datetime, select=self._select, continuation_token=continuation_token, - cls=self._cls, + cls=kwargs.pop("cls", None) or _return_deserialized_and_headers, ) def _extract_data_cb(self, get_next_return): @@ -593,17 +596,16 @@ def __init__(self, command: Callable, **kwargs): self._label = kwargs.get("label") self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") - self._cls = kwargs.get("cls") self._deserializer = lambda objs: [ConfigurationSetting._from_generated(x) for x in objs] - async def _get_next_cb(self, continuation_token): + async def _get_next_cb(self, continuation_token, **kwargs): return await self._command( key=self._key, label=self._label, accept_datetime=self._accept_datetime, select=self._select, continuation_token=continuation_token, - cls=self._cls, + cls=kwargs.pop("cls", None) or _return_deserialized_and_headers, ) async def _extract_data_cb(self, get_next_return): diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py index 944539773e0b..b7e5ebb15c7e 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py @@ -25,7 +25,6 @@ from azure.core.rest import AsyncHttpResponse, HttpRequest from azure.core.utils import CaseInsensitiveDict from ._sync_token_async import AsyncSyncTokenPolicy -from .._azure_appconfiguration_client import _return_deserialized_and_headers from .._azure_appconfiguration_error import ResourceReadOnlyError from .._azure_appconfiguration_requests import AppConfigRequestsCredentialsPolicy from .._generated.aio import AzureAppConfiguration @@ -232,7 +231,6 @@ def list_configuration_settings(self, *args, **kwargs) -> AsyncItemPaged[Configu label=label_filter, accept_datetime=accept_datetime, select=select, - cls=_return_deserialized_and_headers, page_iterator_class=ConfigurationSettingPropertiesPagedAsync, ) except binascii.Error as exc: From 6189c7a126a272d5dec2730ddd7aa220b12fd556 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 14 Mar 2024 18:09:33 -0700 Subject: [PATCH 21/24] Change to get Etag value via `get` --- .../azure-appconfiguration/azure/appconfiguration/_models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py index 3db067ad1dc5..e6d09a59d71b 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py @@ -575,7 +575,7 @@ def _get_next_cb(self, continuation_token, **kwargs): def _extract_data_cb(self, get_next_return): deserialized, response_headers = get_next_return - self.etag = response_headers.get('ETag') + self.etag = response_headers.pop('ETag') return deserialized.next_link or None, iter(self._deserializer(deserialized.items)) @@ -610,5 +610,5 @@ async def _get_next_cb(self, continuation_token, **kwargs): async def _extract_data_cb(self, get_next_return): deserialized, response_headers = get_next_return - self.etag = response_headers.get('ETag') + self.etag = response_headers.pop('ETag') return deserialized.next_link or None, AsyncList(self._deserializer(deserialized.items)) From 6e0cfcf48968e52a1c3f6b8cc2b83c9ae17e14a8 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 14 Mar 2024 18:34:02 -0700 Subject: [PATCH 22/24] Fix mypy --- .../azure/appconfiguration/_azure_appconfiguration_client.py | 2 +- .../aio/_azure_appconfiguration_client_async.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py index 957b9c63711a..fe035c7317f5 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py @@ -218,7 +218,7 @@ def list_configuration_settings( ) key_filter, kwargs = get_key_filter(*args, **kwargs) label_filter, kwargs = get_label_filter(*args, **kwargs) - command = functools.partial(self._impl.get_key_values_in_one_page, **kwargs) + command = functools.partial(self._impl.get_key_values_in_one_page, **kwargs) # type: ignore[attr-defined] return ItemPaged( command, key=key_filter, diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py index b7e5ebb15c7e..6f4c036f284a 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py @@ -224,7 +224,7 @@ def list_configuration_settings(self, *args, **kwargs) -> AsyncItemPaged[Configu ) key_filter, kwargs = get_key_filter(*args, **kwargs) label_filter, kwargs = get_label_filter(*args, **kwargs) - command = functools.partial(self._impl.get_key_values_in_one_page, **kwargs) + command = functools.partial(self._impl.get_key_values_in_one_page, **kwargs) # type: ignore[attr-defined] return AsyncItemPaged( command, key=key_filter, From 5286334f8f5a2ecfa70085392dbc4dbde7f8e978 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 14 Mar 2024 19:23:55 -0700 Subject: [PATCH 23/24] Run black --- .../_azure_appconfiguration_client.py | 10 +- .../_generated/aio/operations/_patch.py | 9 +- .../_generated/operations/_patch.py | 9 +- .../azure/appconfiguration/_models.py | 12 +- .../_azure_appconfiguration_client_async.py | 4 +- .../test_azure_appconfiguration_client.py | 136 ++++++---------- .../test_azure_appconfiguration_client_aad.py | 56 ++----- ...azure_appconfiguration_client_aad_async.py | 52 ++----- ...est_azure_appconfiguration_client_async.py | 146 +++++++----------- .../tests/test_consistency.py | 16 +- 10 files changed, 160 insertions(+), 290 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py index fe035c7317f5..beb098e4b24c 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py @@ -116,7 +116,7 @@ def from_connection_string(cls, connection_string: str, **kwargs: Any) -> "Azure id_credential=id_credential, **kwargs, ) - + @distributed_trace def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs) -> HttpResponse: """Runs a network request using the client's existing pipeline. @@ -196,9 +196,7 @@ def list_configuration_settings( """ @distributed_trace - def list_configuration_settings( - self, *args, **kwargs - ) -> ItemPaged[ConfigurationSetting]: + def list_configuration_settings(self, *args, **kwargs) -> ItemPaged[ConfigurationSetting]: accept_datetime = kwargs.pop("accept_datetime", None) if isinstance(accept_datetime, datetime): accept_datetime = str(accept_datetime) @@ -218,7 +216,7 @@ def list_configuration_settings( ) key_filter, kwargs = get_key_filter(*args, **kwargs) label_filter, kwargs = get_label_filter(*args, **kwargs) - command = functools.partial(self._impl.get_key_values_in_one_page, **kwargs) # type: ignore[attr-defined] + command = functools.partial(self._impl.get_key_values_in_one_page, **kwargs) # type: ignore[attr-defined] return ItemPaged( command, key=key_filter, @@ -230,7 +228,7 @@ def list_configuration_settings( except binascii.Error as exc: raise binascii.Error("Connection string secret has incorrect padding") from exc - + @distributed_trace def get_configuration_setting( self, diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/aio/operations/_patch.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/aio/operations/_patch.py index bebc16a9a44d..0c6a25151308 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/aio/operations/_patch.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/aio/operations/_patch.py @@ -147,13 +147,16 @@ def prepare_request(next_link=None): response_headers = response.headers deserialized = self._deserialize("KeyValueListResult", pipeline_response) - + if cls: return cls(pipeline_response, deserialized, response_headers) - + return deserialized -__all__: List[str] = ["AzureAppConfigurationOperationsMixin"] # Add all objects you want publicly available to users at this package level + +__all__: List[str] = [ + "AzureAppConfigurationOperationsMixin" +] # Add all objects you want publicly available to users at this package level def patch_sdk(): diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py index fa1f0028d87e..64039fa2983a 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_generated/operations/_patch.py @@ -151,13 +151,16 @@ def prepare_request(next_link=None): response_headers = response.headers deserialized = self._deserialize("KeyValueListResult", pipeline_response) - + if cls: return cls(pipeline_response, deserialized, response_headers) - + return deserialized -__all__: List[str] = ["AzureAppConfigurationOperationsMixin"] # Add all objects you want publicly available to users at this package level + +__all__: List[str] = [ + "AzureAppConfigurationOperationsMixin" +] # Add all objects you want publicly available to users at this package level def patch_sdk(): diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py index e6d09a59d71b..36c5bab74a40 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py @@ -549,7 +549,7 @@ class ConfigurationSettingPropertiesPaged(PageIterator): etag: str """The etag of current page.""" - + def __init__(self, command: Callable, **kwargs): super(ConfigurationSettingPropertiesPaged, self).__init__( self._get_next_cb, @@ -562,7 +562,7 @@ def __init__(self, command: Callable, **kwargs): self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") self._deserializer = lambda objs: [ConfigurationSetting._from_generated(x) for x in objs] - + def _get_next_cb(self, continuation_token, **kwargs): return self._command( key=self._key, @@ -575,7 +575,7 @@ def _get_next_cb(self, continuation_token, **kwargs): def _extract_data_cb(self, get_next_return): deserialized, response_headers = get_next_return - self.etag = response_headers.pop('ETag') + self.etag = response_headers.pop("ETag") return deserialized.next_link or None, iter(self._deserializer(deserialized.items)) @@ -584,7 +584,7 @@ class ConfigurationSettingPropertiesPagedAsync(AsyncPageIterator): etag: str """The etag of current page.""" - + def __init__(self, command: Callable, **kwargs): super(ConfigurationSettingPropertiesPagedAsync, self).__init__( self._get_next_cb, @@ -597,7 +597,7 @@ def __init__(self, command: Callable, **kwargs): self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") self._deserializer = lambda objs: [ConfigurationSetting._from_generated(x) for x in objs] - + async def _get_next_cb(self, continuation_token, **kwargs): return await self._command( key=self._key, @@ -610,5 +610,5 @@ async def _get_next_cb(self, continuation_token, **kwargs): async def _extract_data_cb(self, get_next_return): deserialized, response_headers = get_next_return - self.etag = response_headers.pop('ETag') + self.etag = response_headers.pop("ETag") return deserialized.next_link or None, AsyncList(self._deserializer(deserialized.items)) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py index 6f4c036f284a..c98df10a329a 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py @@ -139,7 +139,7 @@ async def send_request(self, request: HttpRequest, *, stream: bool = False, **kw :rtype: ~azure.core.rest.AsyncHttpResponse """ return await self._impl._send_request(request, stream=stream, **kwargs) - + @overload def list_configuration_settings( self, @@ -224,7 +224,7 @@ def list_configuration_settings(self, *args, **kwargs) -> AsyncItemPaged[Configu ) key_filter, kwargs = get_key_filter(*args, **kwargs) label_filter, kwargs = get_label_filter(*args, **kwargs) - command = functools.partial(self._impl.get_key_values_in_one_page, **kwargs) # type: ignore[attr-defined] + command = functools.partial(self._impl.get_key_values_in_one_page, **kwargs) # type: ignore[attr-defined] return AsyncItemPaged( command, key=key_filter, diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py index 88b40700580d..88fb537cd07a 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py @@ -223,9 +223,7 @@ def test_delete_configuration_setting_with_etag(self, appconfiguration_connectio @recorded_by_proxy def test_list_configuration_settings_key_label(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) items = list(self.client.list_configuration_settings(KEY, LABEL)) assert len(items) == 1 @@ -262,9 +260,7 @@ def test_list_configuration_settings_key_label(self, appconfiguration_connection @recorded_by_proxy def test_list_configuration_settings_only_label(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) items = list(self.client.list_configuration_settings(label_filter=LABEL)) assert len(items) == 1 @@ -275,9 +271,7 @@ def test_list_configuration_settings_only_label(self, appconfiguration_connectio @recorded_by_proxy def test_list_configuration_settings_only_key(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) items = list(self.client.list_configuration_settings(KEY)) assert len(items) == 2 @@ -288,9 +282,7 @@ def test_list_configuration_settings_only_key(self, appconfiguration_connection_ @recorded_by_proxy def test_list_configuration_settings_fields(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) items = list( self.client.list_configuration_settings(key_filter="*", label_filter=LABEL, fields=["key", "content_type"]) @@ -303,9 +295,7 @@ def test_list_configuration_settings_fields(self, appconfiguration_connection_st @recorded_by_proxy def test_list_configuration_settings_reserved_chars(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") client = self.create_client(appconfiguration_connection_string) reserved_char_kv = ConfigurationSetting(key=KEY, label=LABEL_RESERVED_CHARS, value=TEST_VALUE) reserved_char_kv = client.add_configuration_setting(reserved_char_kv) @@ -319,9 +309,7 @@ def test_list_configuration_settings_reserved_chars(self, appconfiguration_conne @recorded_by_proxy def test_list_configuration_settings_contains(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) items = list(self.client.list_configuration_settings(label_filter=LABEL + "*")) assert len(items) == 1 @@ -332,9 +320,7 @@ def test_list_configuration_settings_contains(self, appconfiguration_connection_ @recorded_by_proxy def test_list_configuration_settings_correct_etag(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") client = self.create_client(appconfiguration_connection_string) to_list_kv = self.create_config_setting() self.add_for_test(client, to_list_kv) @@ -353,9 +339,7 @@ def test_list_configuration_settings_correct_etag(self, appconfiguration_connect @recorded_by_proxy def test_list_configuration_settings_multi_pages(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") client = self.create_client(appconfiguration_connection_string) # create PAGE_SIZE+1 configuration settings to have at least two pages try: @@ -387,9 +371,7 @@ def test_list_configuration_settings_multi_pages(self, appconfiguration_connecti @recorded_by_proxy def test_list_configuration_settings_no_label(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) items = self.client.list_configuration_settings(label_filter="\0") assert len(list(items)) > 0 @@ -399,9 +381,7 @@ def test_list_configuration_settings_no_label(self, appconfiguration_connection_ @recorded_by_proxy def test_list_configuration_settings_only_accepttime(self, appconfiguration_connection_string, **kwargs): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") recorded_variables = kwargs.pop("variables", {}) recorded_variables.setdefault("timestamp", str(datetime.utcnow())) @@ -426,9 +406,7 @@ def test_list_configuration_settings_only_accepttime(self, appconfiguration_conn @recorded_by_proxy def test_list_revisions_key_label(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) to_list1 = self.create_config_setting() items = list(self.client.list_revisions(label_filter=to_list1.label, key_filter=to_list1.key)) @@ -440,9 +418,7 @@ def test_list_revisions_key_label(self, appconfiguration_connection_string): @recorded_by_proxy def test_list_revisions_only_label(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) items = list(self.client.list_revisions(label_filter=LABEL)) assert len(items) >= 1 @@ -453,9 +429,7 @@ def test_list_revisions_only_label(self, appconfiguration_connection_string): @recorded_by_proxy def test_list_revisions_key_no_label(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) items = list(self.client.list_revisions(key_filter=KEY)) assert len(items) >= 1 @@ -466,9 +440,7 @@ def test_list_revisions_key_no_label(self, appconfiguration_connection_string): @recorded_by_proxy def test_list_revisions_fields(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) items = list(self.client.list_revisions(key_filter="*", label_filter=LABEL, fields=["key", "content_type"])) assert all(x.key and not x.label and x.content_type and not x.tags and not x.etag for x in items) @@ -948,9 +920,7 @@ def test_breaking_with_secret_reference_configuration_setting(self, appconfigura @recorded_by_proxy def test_create_snapshot(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -971,9 +941,7 @@ def test_create_snapshot(self, appconfiguration_connection_string): @recorded_by_proxy def test_update_snapshot_status(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -993,9 +961,7 @@ def test_update_snapshot_status(self, appconfiguration_connection_string): @recorded_by_proxy def test_update_snapshot_status_with_etag(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -1017,9 +983,7 @@ def test_update_snapshot_status_with_etag(self, appconfiguration_connection_stri @recorded_by_proxy def test_list_snapshots(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) result = self.client.list_snapshots() @@ -1045,9 +1009,7 @@ def test_list_snapshots(self, appconfiguration_connection_string): @recorded_by_proxy def test_list_snapshot_configuration_settings(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -1064,9 +1026,7 @@ def test_list_snapshot_configuration_settings(self, appconfiguration_connection_ @recorded_by_proxy def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") with AzureAppConfigurationClient.from_connection_string(appconfiguration_connection_string) as client: # prepare 200 configuration settings for i in range(200): @@ -1077,7 +1037,7 @@ def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_conn ) ) # there will have 2 pages while listing, there are 100 configuration settings per page. - + # get page etags page_etags = [] items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") @@ -1085,34 +1045,35 @@ def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_conn for page in iterator: etag = iterator.etag page_etags.append(etag) - - # monitor page updates without changes + + # monitor page updates without changes continuation_token = None index = 0 request = HttpRequest( method="GET", url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", - headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + headers={ + "If-None-Match": page_etags[index], + "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json", + }, ) first_page_response = client.send_request(request) assert first_page_response.status_code == 304 - - link = first_page_response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None + + link = first_page_response.headers.get("Link", None) + continuation_token = link[1 : link.index(">")] if link else None index += 1 while continuation_token: request = HttpRequest( - method="GET", - url=f"{continuation_token}", - headers={"If-None-Match": page_etags[index]} + method="GET", url=f"{continuation_token}", headers={"If-None-Match": page_etags[index]} ) index += 1 response = client.send_request(request) assert response.status_code == 304 - - link = response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - + + link = response.headers.get("Link", None) + continuation_token = link[1 : link.index(">")] if link else None + # do some changes client.add_configuration_setting( ConfigurationSetting( @@ -1121,7 +1082,7 @@ def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_conn ) ) # now we have three pages, 100 settings in first two pages and 1 setting in the last page - + # get page etags after updates new_page_etags = [] items = client.list_configuration_settings(key_filter="sample_key_*", label_filter="sample_label_*") @@ -1129,31 +1090,32 @@ def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_conn for page in iterator: etag = iterator.etag new_page_etags.append(etag) - + assert page_etags[0] == new_page_etags[0] assert page_etags[1] != new_page_etags[1] assert page_etags[2] != new_page_etags[2] - + # monitor page after updates continuation_token = None index = 0 request = HttpRequest( method="GET", url="/kv?key=sample_key_%2A&label=sample_label_%2A&api-version=2023-10-01", - headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + headers={ + "If-None-Match": page_etags[index], + "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json", + }, ) first_page_response = client.send_request(request) # 304 means the page doesn't have changes. assert first_page_response.status_code == 304 - - link = first_page_response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None + + link = first_page_response.headers.get("Link", None) + continuation_token = link[1 : link.index(">")] if link else None index += 1 while continuation_token: request = HttpRequest( - method="GET", - url=f"{continuation_token}", - headers={"If-None-Match": page_etags[index]} + method="GET", url=f"{continuation_token}", headers={"If-None-Match": page_etags[index]} ) index += 1 response = client.send_request(request) @@ -1163,9 +1125,9 @@ def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_conn items = response.json()["items"] for item in items: print(f"Key: {item['key']}, Label: {item['label']}") - - link = response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None + + link = response.headers.get("Link", None) + continuation_token = link[1 : link.index(">")] if link else None # clean up config_settings = client.list_configuration_settings() diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad.py index 982b25ca8e17..92fd27c8bcbe 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad.py @@ -203,9 +203,7 @@ def test_delete_configuration_setting_with_etag(self, appconfiguration_endpoint_ @recorded_by_proxy def test_list_configuration_settings_key_label(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_configuration_settings(label_filter=LABEL, key_filter=KEY)) assert len(items) == 1 @@ -216,9 +214,7 @@ def test_list_configuration_settings_key_label(self, appconfiguration_endpoint_s @recorded_by_proxy def test_list_configuration_settings_only_label(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_configuration_settings(label_filter=LABEL)) assert len(items) == 1 @@ -229,9 +225,7 @@ def test_list_configuration_settings_only_label(self, appconfiguration_endpoint_ @recorded_by_proxy def test_list_configuration_settings_only_key(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_configuration_settings(key_filter=KEY)) assert len(items) == 2 @@ -242,9 +236,7 @@ def test_list_configuration_settings_only_key(self, appconfiguration_endpoint_st @recorded_by_proxy def test_list_configuration_settings_fields(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list( self.client.list_configuration_settings(key_filter="*", label_filter=LABEL, fields=["key", "content_type"]) @@ -257,9 +249,7 @@ def test_list_configuration_settings_fields(self, appconfiguration_endpoint_stri @recorded_by_proxy def test_list_configuration_settings_reserved_chars(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") client = self.create_aad_client(appconfiguration_endpoint_string) reserved_char_kv = ConfigurationSetting(key=KEY, label=LABEL_RESERVED_CHARS, value=TEST_VALUE) reserved_char_kv = client.add_configuration_setting(reserved_char_kv) @@ -273,9 +263,7 @@ def test_list_configuration_settings_reserved_chars(self, appconfiguration_endpo @recorded_by_proxy def test_list_configuration_settings_contains(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_configuration_settings(label_filter=LABEL + "*")) assert len(items) == 1 @@ -286,9 +274,7 @@ def test_list_configuration_settings_contains(self, appconfiguration_endpoint_st @recorded_by_proxy def test_list_configuration_settings_correct_etag(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") client = self.create_aad_client(appconfiguration_endpoint_string) to_list_kv = self.create_config_setting() self.add_for_test(client, to_list_kv) @@ -307,9 +293,7 @@ def test_list_configuration_settings_correct_etag(self, appconfiguration_endpoin @recorded_by_proxy def test_list_configuration_settings_multi_pages(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") client = self.create_aad_client(appconfiguration_endpoint_string) # create PAGE_SIZE+1 configuration settings to have at least two pages try: @@ -341,9 +325,7 @@ def test_list_configuration_settings_multi_pages(self, appconfiguration_endpoint @recorded_by_proxy def test_list_configuration_settings_no_label(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_endpoint_string, is_aad=True) items = self.client.list_configuration_settings(label_filter="\0") assert len(list(items)) > 0 @@ -353,9 +335,7 @@ def test_list_configuration_settings_no_label(self, appconfiguration_endpoint_st @recorded_by_proxy def test_list_configuration_settings_only_accepttime(self, appconfiguration_endpoint_string, **kwargs): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") recorded_variables = kwargs.pop("variables", {}) self.set_up(appconfiguration_endpoint_string, is_aad=True) exclude_today = self.client.list_configuration_settings( @@ -373,9 +353,7 @@ def test_list_configuration_settings_only_accepttime(self, appconfiguration_endp @recorded_by_proxy def test_list_revisions_key_label(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_endpoint_string, is_aad=True) to_list = self.create_config_setting() items = list(self.client.list_revisions(label_filter=to_list.label, key_filter=to_list.key)) @@ -387,9 +365,7 @@ def test_list_revisions_key_label(self, appconfiguration_endpoint_string): @recorded_by_proxy def test_list_revisions_only_label(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_revisions(label_filter=LABEL)) assert len(items) >= 1 @@ -400,9 +376,7 @@ def test_list_revisions_only_label(self, appconfiguration_endpoint_string): @recorded_by_proxy def test_list_revisions_key_no_label(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_revisions(key_filter=KEY)) assert len(items) >= 1 @@ -413,9 +387,7 @@ def test_list_revisions_key_no_label(self, appconfiguration_endpoint_string): @recorded_by_proxy def test_list_revisions_fields(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") self.set_up(appconfiguration_endpoint_string, is_aad=True) items = list(self.client.list_revisions(key_filter="*", label_filter=LABEL, fields=["key", "content_type"])) assert all(x.key and not x.label and x.content_type and not x.tags and not x.etag for x in items) diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad_async.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad_async.py index 1b21eb29aa46..8c88162d2183 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_aad_async.py @@ -221,9 +221,7 @@ async def test_delete_configuration_setting_with_etag(self, appconfiguration_end @recorded_by_proxy_async async def test_list_configuration_settings_key_label(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list(self.client.list_configuration_settings(label_filter=LABEL, key_filter=KEY)) assert len(items) == 1 @@ -234,9 +232,7 @@ async def test_list_configuration_settings_key_label(self, appconfiguration_endp @recorded_by_proxy_async async def test_list_configuration_settings_only_label(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list(self.client.list_configuration_settings(label_filter=LABEL)) assert len(items) == 1 @@ -247,9 +243,7 @@ async def test_list_configuration_settings_only_label(self, appconfiguration_end @recorded_by_proxy_async async def test_list_configuration_settings_only_key(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list(self.client.list_configuration_settings(key_filter=KEY)) assert len(items) == 2 @@ -260,9 +254,7 @@ async def test_list_configuration_settings_only_key(self, appconfiguration_endpo @recorded_by_proxy_async async def test_list_configuration_settings_fields(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list( self.client.list_configuration_settings(key_filter="*", label_filter=LABEL, fields=["key", "content_type"]) @@ -275,9 +267,7 @@ async def test_list_configuration_settings_fields(self, appconfiguration_endpoin @recorded_by_proxy_async async def test_list_configuration_settings_reserved_chars(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") async with self.create_aad_client(appconfiguration_endpoint_string) as client: reserved_char_kv = ConfigurationSetting(key=KEY, label=LABEL_RESERVED_CHARS, value=TEST_VALUE) reserved_char_kv = await client.add_configuration_setting(reserved_char_kv) @@ -292,9 +282,7 @@ async def test_list_configuration_settings_reserved_chars(self, appconfiguration @recorded_by_proxy_async async def test_list_configuration_settings_contains(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list(self.client.list_configuration_settings(label_filter=LABEL + "*")) assert len(items) == 1 @@ -305,9 +293,7 @@ async def test_list_configuration_settings_contains(self, appconfiguration_endpo @recorded_by_proxy_async async def test_list_configuration_settings_correct_etag(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") async with self.create_aad_client(appconfiguration_endpoint_string) as client: to_list_kv = self.create_config_setting() await self.add_for_test(client, to_list_kv) @@ -326,9 +312,7 @@ async def test_list_configuration_settings_correct_etag(self, appconfiguration_e @recorded_by_proxy_async async def test_list_configuration_settings_multi_pages(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") async with self.create_aad_client(appconfiguration_endpoint_string) as client: # create PAGE_SIZE+1 configuration settings to have at least two pages try: @@ -370,9 +354,7 @@ async def test_list_configuration_settings_null_label(self, appconfiguration_end @recorded_by_proxy_async async def test_list_configuration_settings_only_accepttime(self, appconfiguration_endpoint_string, **kwargs): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") recorded_variables = kwargs.pop("variables", {}) await self.set_up(appconfiguration_endpoint_string, is_aad=True) exclude_today = await self.convert_to_list( @@ -392,9 +374,7 @@ async def test_list_configuration_settings_only_accepttime(self, appconfiguratio @recorded_by_proxy_async async def test_list_revisions_key_label(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_endpoint_string, is_aad=True) to_list = self.create_config_setting() items = await self.convert_to_list( @@ -408,9 +388,7 @@ async def test_list_revisions_key_label(self, appconfiguration_endpoint_string): @recorded_by_proxy_async async def test_list_revisions_only_label(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list(self.client.list_revisions(label_filter=LABEL)) assert len(items) >= 1 @@ -421,9 +399,7 @@ async def test_list_revisions_only_label(self, appconfiguration_endpoint_string) @recorded_by_proxy_async async def test_list_revisions_key_no_label(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list(self.client.list_revisions(key_filter=KEY)) assert len(items) >= 1 @@ -434,9 +410,7 @@ async def test_list_revisions_key_no_label(self, appconfiguration_endpoint_strin @recorded_by_proxy_async async def test_list_revisions_fields(self, appconfiguration_endpoint_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_endpoint_string, is_aad=True) items = await self.convert_to_list( self.client.list_revisions(key_filter="*", label_filter=LABEL, fields=["key", "content_type"]) diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py index 3b56436348cb..9a9e204c1c15 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client_async.py @@ -224,9 +224,7 @@ async def test_delete_configuration_setting_with_etag(self, appconfiguration_con @recorded_by_proxy_async async def test_list_configuration_settings_key_label(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_configuration_settings(KEY, LABEL)) assert len(items) == 1 @@ -263,9 +261,7 @@ async def test_list_configuration_settings_key_label(self, appconfiguration_conn @recorded_by_proxy_async async def test_list_configuration_settings_only_label(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_configuration_settings(label_filter=LABEL)) assert len(items) == 1 @@ -276,9 +272,7 @@ async def test_list_configuration_settings_only_label(self, appconfiguration_con @recorded_by_proxy_async async def test_list_configuration_settings_only_key(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_configuration_settings(KEY)) assert len(items) == 2 @@ -289,9 +283,7 @@ async def test_list_configuration_settings_only_key(self, appconfiguration_conne @recorded_by_proxy_async async def test_list_configuration_settings_fields(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list( self.client.list_configuration_settings(key_filter="*", label_filter=LABEL, fields=["key", "content_type"]) @@ -304,9 +296,7 @@ async def test_list_configuration_settings_fields(self, appconfiguration_connect @recorded_by_proxy_async async def test_list_configuration_settings_reserved_chars(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") async with self.create_client(appconfiguration_connection_string) as client: reserved_char_kv = ConfigurationSetting(key=KEY, label=LABEL_RESERVED_CHARS, value=TEST_VALUE) reserved_char_kv = await client.add_configuration_setting(reserved_char_kv) @@ -320,9 +310,7 @@ async def test_list_configuration_settings_reserved_chars(self, appconfiguration @recorded_by_proxy_async async def test_list_configuration_settings_contains(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_configuration_settings(label_filter=LABEL + "*")) assert len(items) == 1 @@ -333,9 +321,7 @@ async def test_list_configuration_settings_contains(self, appconfiguration_conne @recorded_by_proxy_async async def test_list_configuration_settings_correct_etag(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") async with self.create_client(appconfiguration_connection_string) as client: to_list_kv = self.create_config_setting() await self.add_for_test(client, to_list_kv) @@ -354,9 +340,7 @@ async def test_list_configuration_settings_correct_etag(self, appconfiguration_c @recorded_by_proxy_async async def test_list_configuration_settings_multi_pages(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") async with self.create_client(appconfiguration_connection_string) as client: # create PAGE_SIZE+1 configuration settings to have at least two pages try: @@ -390,9 +374,7 @@ async def test_list_configuration_settings_multi_pages(self, appconfiguration_co @recorded_by_proxy_async async def test_list_configuration_settings_no_label(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_configuration_settings(label_filter="\0")) assert len(items) > 0 @@ -402,9 +384,7 @@ async def test_list_configuration_settings_no_label(self, appconfiguration_conne @recorded_by_proxy_async async def test_list_configuration_settings_only_accepttime(self, appconfiguration_connection_string, **kwargs): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") recorded_variables = kwargs.pop("variables", {}) recorded_variables.setdefault("timestamp", str(datetime.utcnow())) @@ -431,9 +411,7 @@ async def test_list_configuration_settings_only_accepttime(self, appconfiguratio @recorded_by_proxy_async async def test_list_revisions_key_label(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) to_list1 = self.create_config_setting() items = await self.convert_to_list( @@ -447,9 +425,7 @@ async def test_list_revisions_key_label(self, appconfiguration_connection_string @recorded_by_proxy_async async def test_list_revisions_only_label(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_revisions(label_filter=LABEL)) assert len(items) >= 1 @@ -460,9 +436,7 @@ async def test_list_revisions_only_label(self, appconfiguration_connection_strin @recorded_by_proxy_async async def test_list_revisions_key_no_label(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list(self.client.list_revisions(key_filter=KEY)) assert len(items) >= 1 @@ -473,9 +447,7 @@ async def test_list_revisions_key_no_label(self, appconfiguration_connection_str @recorded_by_proxy_async async def test_list_revisions_fields(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) items = await self.convert_to_list( self.client.list_revisions(key_filter="*", label_filter=LABEL, fields=["key", "content_type"]) @@ -971,9 +943,7 @@ async def test_breaking_with_secret_reference_configuration_setting(self, appcon @recorded_by_proxy_async async def test_create_snapshot(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -994,9 +964,7 @@ async def test_create_snapshot(self, appconfiguration_connection_string): @recorded_by_proxy_async async def test_update_snapshot_status(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -1016,9 +984,7 @@ async def test_update_snapshot_status(self, appconfiguration_connection_string): @recorded_by_proxy_async async def test_update_snapshot_status_with_etag(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -1040,9 +1006,7 @@ async def test_update_snapshot_status_with_etag(self, appconfiguration_connectio @recorded_by_proxy_async async def test_list_snapshots(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) result = await self.convert_to_list(self.client.list_snapshots()) @@ -1068,9 +1032,7 @@ async def test_list_snapshots(self, appconfiguration_connection_string): @recorded_by_proxy_async async def test_list_snapshot_configuration_settings(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") await self.set_up(appconfiguration_connection_string) snapshot_name = self.get_resource_name("snapshot") filters = [ConfigurationSettingsFilter(key=KEY, label=LABEL)] @@ -1082,14 +1044,12 @@ async def test_list_snapshot_configuration_settings(self, appconfiguration_conne assert len(items) == 1 await self.tear_down() - + @app_config_decorator_async @recorded_by_proxy_async async def test_monitor_configuration_settings_by_page_etag(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") async with AzureAppConfigurationClient.from_connection_string(appconfiguration_connection_string) as client: # prepare 200 configuration settings for i in range(200): @@ -1100,42 +1060,45 @@ async def test_monitor_configuration_settings_by_page_etag(self, appconfiguratio ) ) # there will have 2 pages while listing, there are 100 configuration settings per page. - + # get page etags page_etags = [] - items = client.list_configuration_settings(key_filter="async_sample_key_*", label_filter="async_sample_label_*") + items = client.list_configuration_settings( + key_filter="async_sample_key_*", label_filter="async_sample_label_*" + ) iterator = items.by_page() async for page in iterator: etag = iterator.etag page_etags.append(etag) - - # monitor page updates without changes + + # monitor page updates without changes continuation_token = None index = 0 request = HttpRequest( method="GET", url="/kv?key=async_sample_key_%2A&label=async_sample_label_%2A&api-version=2023-10-01", - headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + headers={ + "If-None-Match": page_etags[index], + "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json", + }, ) first_page_response = await client.send_request(request) assert first_page_response.status_code == 304 - - link = first_page_response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None + + link = first_page_response.headers.get("Link", None) + continuation_token = link[1 : link.index(">")] if link else None index += 1 while continuation_token: request = HttpRequest( - method="GET", - url=f"{continuation_token}", - headers={"If-None-Match": page_etags[index]} + method="GET", url=f"{continuation_token}", headers={"If-None-Match": page_etags[index]} ) index += 1 response = await client.send_request(request) assert response.status_code == 304 - - link = response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None - + + link = response.headers.get("Link", None) + continuation_token = link[1 : link.index(">")] if link else None + # do some changes await client.add_configuration_setting( ConfigurationSetting( @@ -1144,39 +1107,42 @@ async def test_monitor_configuration_settings_by_page_etag(self, appconfiguratio ) ) # now we have three pages, 100 settings in first two pages and 1 setting in the last page - + # get page etags after updates new_page_etags = [] - items = client.list_configuration_settings(key_filter="async_sample_key_*", label_filter="async_sample_label_*") + items = client.list_configuration_settings( + key_filter="async_sample_key_*", label_filter="async_sample_label_*" + ) iterator = items.by_page() async for page in iterator: etag = iterator.etag new_page_etags.append(etag) - + assert page_etags[0] == new_page_etags[0] assert page_etags[1] != new_page_etags[1] assert page_etags[2] != new_page_etags[2] - + # monitor page after updates continuation_token = None index = 0 request = HttpRequest( method="GET", url="/kv?key=async_sample_key_%2A&label=async_sample_label_%2A&api-version=2023-10-01", - headers={"If-None-Match": page_etags[index], "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json"} + headers={ + "If-None-Match": page_etags[index], + "Accept": "application/vnd.microsoft.appconfig.kvset+json, application/problem+json", + }, ) first_page_response = await client.send_request(request) # 304 means the page doesn't have changes. assert first_page_response.status_code == 304 - - link = first_page_response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None + + link = first_page_response.headers.get("Link", None) + continuation_token = link[1 : link.index(">")] if link else None index += 1 while continuation_token: request = HttpRequest( - method="GET", - url=f"{continuation_token}", - headers={"If-None-Match": page_etags[index]} + method="GET", url=f"{continuation_token}", headers={"If-None-Match": page_etags[index]} ) index += 1 response = await client.send_request(request) @@ -1186,9 +1152,9 @@ async def test_monitor_configuration_settings_by_page_etag(self, appconfiguratio items = response.json()["items"] for item in items: print(f"Key: {item['key']}, Label: {item['label']}") - - link = response.headers.get('Link', None) - continuation_token = link[1:link.index(">")] if link else None + + link = response.headers.get("Link", None) + continuation_token = link[1 : link.index(">")] if link else None # clean up config_settings = client.list_configuration_settings() diff --git a/sdk/appconfiguration/azure-appconfiguration/tests/test_consistency.py b/sdk/appconfiguration/azure-appconfiguration/tests/test_consistency.py index ad4405d37cf2..808e092780ac 100644 --- a/sdk/appconfiguration/azure-appconfiguration/tests/test_consistency.py +++ b/sdk/appconfiguration/azure-appconfiguration/tests/test_consistency.py @@ -19,9 +19,7 @@ class TestAppConfigurationConsistency(AppConfigTestCase): @recorded_by_proxy def test_update_json_by_value(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") client = self.create_client(appconfiguration_connection_string) key = self.get_resource_name("key") feature_flag = FeatureFlagConfigurationSetting( @@ -59,9 +57,7 @@ def test_update_json_by_value(self, appconfiguration_connection_string): @recorded_by_proxy def test_feature_flag_invalid_json(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") client = self.create_client(appconfiguration_connection_string) key = self.get_resource_name("key") feature_flag = FeatureFlagConfigurationSetting(key, enabled=True) @@ -77,9 +73,7 @@ def test_feature_flag_invalid_json(self, appconfiguration_connection_string): @recorded_by_proxy def test_feature_flag_invalid_json_string(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") client = self.create_client(appconfiguration_connection_string) key = self.get_resource_name("key") feature_flag = FeatureFlagConfigurationSetting(key, enabled=True) @@ -95,9 +89,7 @@ def test_feature_flag_invalid_json_string(self, appconfiguration_connection_stri @recorded_by_proxy def test_feature_flag_invalid_json_access_properties(self, appconfiguration_connection_string): # response header and are missing in python38. - set_custom_default_matcher( - compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date" - ) + set_custom_default_matcher(compare_bodies=False, excluded_headers="x-ms-content-sha256,x-ms-date") client = self.create_client(appconfiguration_connection_string) key = self.get_resource_name("key") feature_flag = FeatureFlagConfigurationSetting(key, enabled=True) From 38e7bb6e53e35ca99036afc5cc26698577a4a6c9 Mon Sep 17 00:00:00 2001 From: YalinLi0312 Date: Thu, 14 Mar 2024 19:34:56 -0700 Subject: [PATCH 24/24] Fix pylint --- .../azure/appconfiguration/_models.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py index 36c5bab74a40..ad515bf392d6 100644 --- a/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py +++ b/sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_models.py @@ -498,11 +498,11 @@ def _from_generated(cls, generated: GeneratedConfigurationSnapshot) -> "Configur return snapshot @classmethod - def _from_deserialized( # pylint:disable=unused-argument + def _from_deserialized( cls, - response: HttpResponse, + response: HttpResponse, # pylint:disable=unused-argument deserialized: GeneratedConfigurationSnapshot, - response_headers: Dict, + response_headers: Dict, # pylint:disable=unused-argument ) -> "ConfigurationSnapshot": if deserialized is None: return deserialized @@ -540,7 +540,7 @@ def _to_generated(self) -> GeneratedConfigurationSnapshot: ) -def _return_deserialized_and_headers(response, deserialized, response_headers): +def _return_deserialized_and_headers(_, deserialized, response_headers): return deserialized, response_headers @@ -561,7 +561,9 @@ def __init__(self, command: Callable, **kwargs): self._label = kwargs.get("label") self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") - self._deserializer = lambda objs: [ConfigurationSetting._from_generated(x) for x in objs] + self._deserializer = lambda objs: [ + ConfigurationSetting._from_generated(x) for x in objs # pylint:disable=protected-access + ] def _get_next_cb(self, continuation_token, **kwargs): return self._command( @@ -596,7 +598,9 @@ def __init__(self, command: Callable, **kwargs): self._label = kwargs.get("label") self._accept_datetime = kwargs.get("accept_datetime") self._select = kwargs.get("select") - self._deserializer = lambda objs: [ConfigurationSetting._from_generated(x) for x in objs] + self._deserializer = lambda objs: [ + ConfigurationSetting._from_generated(x) for x in objs # pylint:disable=protected-access + ] async def _get_next_cb(self, continuation_token, **kwargs): return await self._command(