Skip to content

Commit d5bedbf

Browse files
author
Yalin Li
authored
[AppConfig] Address ApiView feedback (#32914)
1 parent 9900ae4 commit d5bedbf

File tree

7 files changed

+154
-24
lines changed

7 files changed

+154
-24
lines changed

sdk/appconfiguration/azure-appconfiguration/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
### Bugs Fixed
1010

1111
### Other Changes
12+
- Support datetime type for keyword argument `accept_datetime` in `get_snapshot_configuration_settings()`, `list_snapshot_configuration_settings()` and `list_revisions()`.
1213

1314
## 1.5.0b3 (2023-10-10)
1415

sdk/appconfiguration/azure-appconfiguration/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "python",
44
"TagPrefix": "python/appconfiguration/azure-appconfiguration",
5-
"Tag": "python/appconfiguration/azure-appconfiguration_214d709db6"
5+
"Tag": "python/appconfiguration/azure-appconfiguration_e73c991afd"
66
}

sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_azure_appconfiguration_client.py

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# license information.
55
# -------------------------------------------------------------------------
66
import binascii
7+
from datetime import datetime
78
from typing import Any, Dict, List, Mapping, Optional, Union, cast, overload
89
from typing_extensions import Literal
910
from azure.core import MatchConditions
@@ -41,6 +42,8 @@
4142
get_endpoint_from_connection_string,
4243
prep_if_match,
4344
prep_if_none_match,
45+
get_key_filter,
46+
get_label_filter,
4447
)
4548
from ._sync_token import SyncTokenPolicy
4649
from ._user_agent import USER_AGENT
@@ -148,7 +151,7 @@ def _create_appconfig_pipeline(self, credential, credential_scopes, aad_mode=Fal
148151

149152
@overload
150153
def list_configuration_settings(
151-
self, *, key_filter: Optional[str] = None, label_filter: Optional[str] = None, **kwargs: Any
154+
self, key_filter: Optional[str] = None, label_filter: Optional[str] = None, **kwargs: Any
152155
) -> ItemPaged[ConfigurationSetting]:
153156
"""List the configuration settings stored in the configuration service, optionally filtered by
154157
key, label and accept_datetime.
@@ -159,7 +162,8 @@ def list_configuration_settings(
159162
:keyword label_filter: filter results based on their label. '*' can be
160163
used as wildcard in the beginning or end of the filter
161164
:paramtype label_filter: str
162-
:keyword str accept_datetime: retrieve ConfigurationSetting existed at this datetime
165+
:keyword accept_datetime: retrieve ConfigurationSetting existed at this datetime
166+
:paramtype accept_datetime: ~datetime.datetime or str
163167
:keyword list[str] fields: specify which fields to include in the results. Leave None to include all fields
164168
:return: An iterator of :class:`~azure.appconfiguration.ConfigurationSetting`
165169
:rtype: ~azure.core.paging.ItemPaged[~azure.appconfiguration.ConfigurationSetting]
@@ -201,7 +205,10 @@ def list_configuration_settings(
201205
"""
202206

203207
@distributed_trace
204-
def list_configuration_settings(self, **kwargs) -> ItemPaged[ConfigurationSetting]:
208+
def list_configuration_settings(self, *args, **kwargs) -> ItemPaged[ConfigurationSetting]:
209+
accept_datetime = kwargs.pop("accept_datetime", None)
210+
if isinstance(accept_datetime, datetime):
211+
accept_datetime = str(accept_datetime)
205212
select = kwargs.pop("fields", None)
206213
if select:
207214
select = ["locked" if x == "read_only" else x for x in select]
@@ -211,13 +218,17 @@ def list_configuration_settings(self, **kwargs) -> ItemPaged[ConfigurationSettin
211218
if snapshot_name is not None:
212219
return self._impl.get_key_values( # type: ignore
213220
snapshot=snapshot_name,
221+
accept_datetime=accept_datetime,
214222
select=select,
215223
cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs],
216224
**kwargs
217225
)
226+
key_filter, kwargs = get_key_filter(*args, **kwargs)
227+
label_filter, kwargs = get_label_filter(*args, **kwargs)
218228
return self._impl.get_key_values( # type: ignore
219-
key=kwargs.pop("key_filter", None),
220-
label=kwargs.pop("label_filter", None),
229+
key=key_filter,
230+
label=label_filter,
231+
accept_datetime=accept_datetime,
221232
select=select,
222233
cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs],
223234
**kwargs
@@ -244,7 +255,8 @@ def get_configuration_setting(
244255
:type etag: str or None
245256
:param match_condition: The match condition to use upon the etag
246257
:type match_condition: ~azure.core.MatchConditions
247-
:keyword str accept_datetime: retrieve ConfigurationSetting existed at this datetime
258+
:keyword accept_datetime: retrieve ConfigurationSetting existed at this datetime
259+
:paramtype accept_datetime: ~datetime.datetime or str
248260
:return: The matched ConfigurationSetting object
249261
:rtype: ~azure.appconfiguration.ConfigurationSetting or None
250262
:raises: :class:`~azure.core.exceptions.HttpResponseError`, \
@@ -261,6 +273,10 @@ def get_configuration_setting(
261273
key="MyKey", label="MyLabel"
262274
)
263275
"""
276+
accept_datetime = kwargs.pop("accept_datetime", None)
277+
if isinstance(accept_datetime, datetime):
278+
accept_datetime = str(accept_datetime)
279+
264280
error_map: Dict[int, Any] = {}
265281
if match_condition == MatchConditions.IfNotModified:
266282
error_map.update({412: ResourceModifiedError})
@@ -273,6 +289,7 @@ def get_configuration_setting(
273289
key_value = self._impl.get_key_value(
274290
key=key,
275291
label=label,
292+
accept_datetime=accept_datetime,
276293
if_match=prep_if_match(etag, match_condition),
277294
if_none_match=prep_if_none_match(etag, match_condition),
278295
error_map=error_map,
@@ -460,7 +477,8 @@ def list_revisions(
460477
:param label_filter: filter results based on their label. '*' can be
461478
used as wildcard in the beginning or end of the filter
462479
:type label_filter: str
463-
:keyword str accept_datetime: retrieve ConfigurationSetting existed at this datetime
480+
:keyword accept_datetime: retrieve ConfigurationSetting existed at this datetime
481+
:paramtype accept_datetime: ~datetime.datetime or str
464482
:keyword list[str] fields: specify which fields to include in the results. Leave None to include all fields
465483
:return: An iterator of :class:`~azure.appconfiguration.ConfigurationSetting`
466484
:rtype: ~azure.core.paging.ItemPaged[~azure.appconfiguration.ConfigurationSetting]
@@ -485,6 +503,9 @@ def list_revisions(
485503
for item in filtered_revisions:
486504
pass # do something
487505
"""
506+
accept_datetime = kwargs.pop("accept_datetime", None)
507+
if isinstance(accept_datetime, datetime):
508+
accept_datetime = str(accept_datetime)
488509
select = kwargs.pop("fields", None)
489510
if select:
490511
select = ["locked" if x == "read_only" else x for x in select]
@@ -493,6 +514,7 @@ def list_revisions(
493514
return self._impl.get_revisions( # type: ignore
494515
label=label_filter,
495516
key=key_filter,
517+
accept_datetime=accept_datetime,
496518
select=select,
497519
cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs],
498520
**kwargs

sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/_utils.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# -------------------------------------------------------------------------
66

77
from datetime import datetime
8-
from typing import Optional, Tuple
8+
from typing import Optional, Tuple, Dict, Any
99
from azure.core import MatchConditions
1010

1111

@@ -70,3 +70,27 @@ def parse_connection_string(connection_string: str) -> Tuple[str, str, str]:
7070

7171
def get_current_utc_time() -> str:
7272
return str(datetime.utcnow().strftime("%b, %d %Y %H:%M:%S.%f ")) + "GMT"
73+
74+
75+
def get_key_filter(*args, **kwargs) -> Tuple[Optional[str], Dict[str, Any]]:
76+
key_filter = None
77+
if len(args) > 0:
78+
key_filter = args[0]
79+
if "key_filter" in kwargs:
80+
raise TypeError(
81+
"AzureAppConfigurationClient.list_configuration_settings() got multiple values for argument "
82+
"'key_filter'"
83+
)
84+
return key_filter or kwargs.pop("key_filter", None), kwargs
85+
86+
87+
def get_label_filter(*args, **kwargs) -> Tuple[Optional[str], Dict[str, Any]]:
88+
label_filter = None
89+
if len(args) > 1:
90+
label_filter = args[1]
91+
if "label_filter" in kwargs:
92+
raise TypeError(
93+
"AzureAppConfigurationClient.list_configuration_settings() got multiple values for argument "
94+
"'label_filter'"
95+
)
96+
return label_filter or kwargs.pop("label_filter", None), kwargs

sdk/appconfiguration/azure-appconfiguration/azure/appconfiguration/aio/_azure_appconfiguration_client_async.py

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# license information.
55
# -------------------------------------------------------------------------
66
import binascii
7+
from datetime import datetime
78
from typing import Any, Dict, List, Mapping, Optional, Union, cast, overload
89
from typing_extensions import Literal
910
from azure.core import MatchConditions
@@ -35,6 +36,8 @@
3536
get_endpoint_from_connection_string,
3637
prep_if_match,
3738
prep_if_none_match,
39+
get_key_filter,
40+
get_label_filter,
3841
)
3942

4043

@@ -122,7 +125,7 @@ def from_connection_string(cls, connection_string: str, **kwargs: Any) -> "Azure
122125

123126
@overload
124127
def list_configuration_settings(
125-
self, *, key_filter: Optional[str] = None, label_filter: Optional[str] = None, **kwargs: Any
128+
self, key_filter: Optional[str] = None, label_filter: Optional[str] = None, **kwargs: Any
126129
) -> AsyncItemPaged[ConfigurationSetting]:
127130

128131
"""List the configuration settings stored in the configuration service, optionally filtered by
@@ -134,7 +137,8 @@ def list_configuration_settings(
134137
:keyword label_filter: filter results based on their label. '*' can be
135138
used as wildcard in the beginning or end of the filter
136139
:paramtype label_filter: str
137-
:keyword str accept_datetime: retrieve ConfigurationSetting existed at this datetime
140+
:keyword accept_datetime: retrieve ConfigurationSetting existed at this datetime
141+
:paramtype accept_datetime: ~datetime.datetime or str
138142
:keyword list[str] fields: specify which fields to include in the results. Leave None to include all fields
139143
:return: An async iterator of :class:`~azure.appconfiguration.ConfigurationSetting`
140144
:rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.appconfiguration.ConfigurationSetting]
@@ -176,7 +180,11 @@ def list_configuration_settings(
176180
"""
177181

178182
@distributed_trace
179-
def list_configuration_settings(self, **kwargs) -> AsyncItemPaged[ConfigurationSetting]:
183+
def list_configuration_settings(self, *args, **kwargs) -> AsyncItemPaged[ConfigurationSetting]:
184+
accept_datetime = kwargs.pop("accept_datetime", None)
185+
if isinstance(accept_datetime, datetime):
186+
accept_datetime = str(accept_datetime)
187+
180188
select = kwargs.pop("fields", None)
181189
if select:
182190
select = ["locked" if x == "read_only" else x for x in select]
@@ -186,13 +194,17 @@ def list_configuration_settings(self, **kwargs) -> AsyncItemPaged[ConfigurationS
186194
if snapshot_name is not None:
187195
return self._impl.get_key_values( # type: ignore
188196
snapshot=snapshot_name,
197+
accept_datetime=accept_datetime,
189198
select=select,
190199
cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs],
191200
**kwargs
192201
)
202+
key_filter, kwargs = get_key_filter(*args, **kwargs)
203+
label_filter, kwargs = get_label_filter(*args, **kwargs)
193204
return self._impl.get_key_values( # type: ignore
194-
key=kwargs.pop("key_filter", None),
195-
label=kwargs.pop("label_filter", None),
205+
key=key_filter,
206+
label=label_filter,
207+
accept_datetime=accept_datetime,
196208
select=select,
197209
cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs],
198210
**kwargs
@@ -220,7 +232,8 @@ async def get_configuration_setting(
220232
:type etag: str or None
221233
:param match_condition: The match condition to use upon the etag
222234
:type match_condition: ~azure.core.MatchConditions
223-
:keyword str accept_datetime: retrieve ConfigurationSetting existed at this datetime
235+
:keyword accept_datetime: retrieve ConfigurationSetting existed at this datetime
236+
:paramtype accept_datetime: ~datetime.datetime or str
224237
:return: The matched ConfigurationSetting object
225238
:rtype: ~azure.appconfiguration.ConfigurationSetting or None
226239
:raises: :class:`~azure.core.exceptions.HttpResponseError`, \
@@ -238,6 +251,10 @@ async def get_configuration_setting(
238251
key="MyKey", label="MyLabel"
239252
)
240253
"""
254+
accept_datetime = kwargs.pop("accept_datetime", None)
255+
if isinstance(accept_datetime, datetime):
256+
accept_datetime = str(accept_datetime)
257+
241258
error_map: Dict[int, Any] = {}
242259
if match_condition == MatchConditions.IfNotModified:
243260
error_map.update({412: ResourceModifiedError})
@@ -250,6 +267,7 @@ async def get_configuration_setting(
250267
key_value = await self._impl.get_key_value(
251268
key=key,
252269
label=label,
270+
accept_datetime=accept_datetime,
253271
if_match=prep_if_match(etag, match_condition),
254272
if_none_match=prep_if_none_match(etag, match_condition),
255273
error_map=error_map,
@@ -448,7 +466,8 @@ def list_revisions(
448466
:param label_filter: filter results based on their label. '*' can be
449467
used as wildcard in the beginning or end of the filter
450468
:type label_filter: str
451-
:keyword str accept_datetime: retrieve ConfigurationSetting existed at this datetime
469+
:keyword accept_datetime: retrieve ConfigurationSetting existed at this datetime
470+
:paramtype accept_datetime: ~datetime.datetime or str
452471
:keyword list[str] fields: specify which fields to include in the results. Leave None to include all fields
453472
:return: An async iterator of :class:`~azure.appconfiguration.ConfigurationSetting`
454473
:rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.appconfiguration.ConfigurationSetting]
@@ -474,6 +493,9 @@ def list_revisions(
474493
async for item in filtered_revisions:
475494
pass # do something
476495
"""
496+
accept_datetime = kwargs.pop("accept_datetime", None)
497+
if isinstance(accept_datetime, datetime):
498+
accept_datetime = str(accept_datetime)
477499
select = kwargs.pop("fields", None)
478500
if select:
479501
select = ["locked" if x == "read_only" else x for x in select]
@@ -482,6 +504,7 @@ def list_revisions(
482504
return self._impl.get_revisions( # type: ignore
483505
label=label_filter,
484506
key=key_filter,
507+
accept_datetime=accept_datetime,
485508
select=select,
486509
cls=lambda objs: [ConfigurationSetting._from_generated(x) for x in objs],
487510
**kwargs

sdk/appconfiguration/azure-appconfiguration/tests/test_azure_appconfiguration_client.py

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
# --------------------------------------------------------------------------
66
import pytest
77
import copy
8-
import datetime
98
import json
109
import re
10+
from datetime import datetime, timezone
1111
from azure.core import MatchConditions
1212
from azure.core.exceptions import (
1313
AzureError,
@@ -222,9 +222,35 @@ def test_delete_configuration_setting_with_etag(self, appconfiguration_connectio
222222
@recorded_by_proxy
223223
def test_list_configuration_settings_key_label(self, appconfiguration_connection_string):
224224
self.set_up(appconfiguration_connection_string)
225-
items = list(self.client.list_configuration_settings(label_filter=LABEL, key_filter=KEY))
225+
items = list(self.client.list_configuration_settings(KEY, LABEL))
226226
assert len(items) == 1
227227
assert all(x.label == LABEL and x.label == LABEL for x in items)
228+
229+
with pytest.raises(TypeError) as ex:
230+
self.client.list_configuration_settings("MyKey1", key_filter="MyKey2")
231+
assert (
232+
str(ex.value)
233+
== "AzureAppConfigurationClient.list_configuration_settings() got multiple values for argument 'key_filter'"
234+
)
235+
with pytest.raises(TypeError) as ex:
236+
self.client.list_configuration_settings("MyKey", "MyLabel1", label_filter="MyLabel2")
237+
assert (
238+
str(ex.value)
239+
== "AzureAppConfigurationClient.list_configuration_settings() got multiple values for argument 'label_filter'"
240+
)
241+
with pytest.raises(TypeError) as ex:
242+
self.client.list_configuration_settings("None", key_filter="MyKey")
243+
assert (
244+
str(ex.value)
245+
== "AzureAppConfigurationClient.list_configuration_settings() got multiple values for argument 'key_filter'"
246+
)
247+
with pytest.raises(TypeError) as ex:
248+
self.client.list_configuration_settings("None", "None", label_filter="MyLabel")
249+
assert (
250+
str(ex.value)
251+
== "AzureAppConfigurationClient.list_configuration_settings() got multiple values for argument 'label_filter'"
252+
)
253+
228254
self.tear_down()
229255

230256
@app_config_decorator
@@ -240,7 +266,7 @@ def test_list_configuration_settings_only_label(self, appconfiguration_connectio
240266
@recorded_by_proxy
241267
def test_list_configuration_settings_only_key(self, appconfiguration_connection_string):
242268
self.set_up(appconfiguration_connection_string)
243-
items = list(self.client.list_configuration_settings(key_filter=KEY))
269+
items = list(self.client.list_configuration_settings(KEY))
244270
assert len(items) == 2
245271
assert all(x.key == KEY for x in items)
246272
self.tear_down()
@@ -336,7 +362,7 @@ def test_list_configuration_settings_no_label(self, appconfiguration_connection_
336362
@recorded_by_proxy
337363
def test_list_configuration_settings_only_accepttime(self, appconfiguration_connection_string, **kwargs):
338364
recorded_variables = kwargs.pop("variables", {})
339-
recorded_variables.setdefault("timestamp", str(datetime.datetime.utcnow()))
365+
recorded_variables.setdefault("timestamp", str(datetime.utcnow()))
340366

341367
with self.create_client(appconfiguration_connection_string) as client:
342368
# Confirm all configuration settings are cleaned up
@@ -348,6 +374,10 @@ def test_list_configuration_settings_only_accepttime(self, appconfiguration_conn
348374
revision = client.list_configuration_settings(accept_datetime=recorded_variables.get("timestamp"))
349375
assert len(list(revision)) >= 0
350376

377+
accept_time = datetime(year=2000, month=4, day=1, hour=9, minute=30, second=45, tzinfo=timezone.utc)
378+
revision = client.list_configuration_settings(accept_datetime=accept_time)
379+
assert len(list(revision)) == 0
380+
351381
return recorded_variables
352382

353383
# method: list_revisions

0 commit comments

Comments
 (0)