Skip to content

Commit a91393f

Browse files
committed
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-python into use_azure_core_endcoder
* 'main' of https://github.com/Azure/azure-sdk-for-python: [Key Vault] Add 7.3-preview support for administration (#20364) Fix Monitor opentelemetry exporter readme issues (#19038) More Renaming in query (#20303) Update CODEOWNERS (#20366) [ServiceBus] update migration guide with message count info (#20360) [rest] change text from a property to a method (#20290) Handle value types for results (#20358)
2 parents 2552c19 + 521d56d commit a91393f

File tree

75 files changed

+5555
-820
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+5555
-820
lines changed

.github/CODEOWNERS

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
/sdk/communication/ @acsdevx-msft
4242

4343
# PRLabel: %KeyVault
44-
/sdk/keyvault/ @schaabs @chlowell @mccoyp
44+
/sdk/keyvault/ @schaabs @chlowell @mccoyp @YalinLi0312
4545

4646
# PRLabel: %Monitor - LogAnalytics
4747
/sdk/loganalytics/ @alexeldeib
@@ -143,4 +143,4 @@
143143

144144
# Add owners for notifications for specific pipelines
145145
/eng/pipelines/templates/jobs/tests-nightly-python.yml @lmazuel @mccoyp
146-
/eng/pipelines/aggregate-reports.yml @lmazuel @mccoyp
146+
/eng/pipelines/aggregate-reports.yml @lmazuel @mccoyp @YalinLi0312

sdk/core/azure-core/CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66

77
- We now use `azure.core.serialization.AzureJSONEncoder` to serialize `json` input to `azure.core.rest.HttpRequest`.
88

9-
### Breaking Changes
9+
### Breaking Changes in the Provisional `azure.core.rest` package
10+
11+
- The `text` property on `azure.core.rest.HttpResponse` and `azure.core.rest.AsyncHttpResponse` has changed to a method, which also takes
12+
an `encoding` parameter.
1013

1114
### Bugs Fixed
1215

sdk/core/azure-core/azure/core/rest/_helpers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ def get_charset_encoding(response):
294294

295295
def decode_to_text(encoding, content):
296296
# type: (Optional[str], bytes) -> str
297+
if not content:
298+
return ""
297299
if encoding == "utf-8":
298300
encoding = "utf-8-sig"
299301
if encoding:

sdk/core/azure-core/azure/core/rest/_requests_basic.py

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -61,36 +61,6 @@ def content(self):
6161
# requests throws a RuntimeError if the content for a response is already consumed
6262
raise ResponseNotReadError(self)
6363

64-
@property
65-
def encoding(self):
66-
# type: () -> Optional[str]
67-
retval = super(_RestRequestsTransportResponseBase, self).encoding
68-
if not retval:
69-
# There is a few situation where "requests" magic doesn't fit us:
70-
# - https://github.com/psf/requests/issues/654
71-
# - https://github.com/psf/requests/issues/1737
72-
# - https://github.com/psf/requests/issues/2086
73-
from codecs import BOM_UTF8
74-
if self._internal_response.content[:3] == BOM_UTF8:
75-
retval = "utf-8-sig"
76-
if retval:
77-
if retval == "utf-8":
78-
retval = "utf-8-sig"
79-
return retval
80-
81-
@encoding.setter # type: ignore
82-
def encoding(self, value):
83-
# type: (str) -> None
84-
# ignoring setter bc of known mypy issue https://github.com/python/mypy/issues/1465
85-
self._encoding = value
86-
self._internal_response.encoding = value
87-
88-
@property
89-
def text(self):
90-
# this will trigger errors if response is not read in
91-
self.content # pylint: disable=pointless-statement
92-
return self._internal_response.text
93-
9464
def _stream_download_helper(decompress, response):
9565
if response.is_stream_consumed:
9666
raise StreamConsumedError(response)

sdk/core/azure-core/azure/core/rest/_rest.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -235,17 +235,19 @@ def encoding(self, value):
235235
# type: (str) -> None
236236
"""Sets the response encoding"""
237237
self._encoding = value
238+
self._text = None # clear text cache
238239

239-
@property
240-
def text(self):
241-
# type: (...) -> str
242-
"""Returns the response body as a string"""
243-
if self._text is None:
244-
content = self.content
245-
if not content:
246-
self._text = ""
247-
else:
248-
self._text = decode_to_text(self.encoding, self.content)
240+
def text(self, encoding=None):
241+
# type: (Optional[str]) -> str
242+
"""Returns the response body as a string
243+
244+
:param optional[str] encoding: The encoding you want to decode the text with. Can
245+
also be set independently through our encoding property
246+
:return: The response's content decoded as a string.
247+
"""
248+
if self._text is None or encoding:
249+
encoding_to_pass = encoding or self.encoding
250+
self._text = decode_to_text(encoding_to_pass, self.content)
249251
return self._text
250252

251253
def json(self):
@@ -259,7 +261,7 @@ def json(self):
259261
# this will trigger errors if response is not read in
260262
self.content # pylint: disable=pointless-statement
261263
if not self._json:
262-
self._json = loads(self.text)
264+
self._json = loads(self.text())
263265
return self._json
264266

265267
def raise_for_status(self):
@@ -314,7 +316,6 @@ class HttpResponse(_HttpResponseBase): # pylint: disable=too-many-instance-attr
314316
:ivar str text: The response body as a string.
315317
:ivar request: The request that resulted in this response.
316318
:vartype request: ~azure.core.rest.HttpRequest
317-
:ivar internal_response: The object returned from the HTTP library.
318319
:ivar str content_type: The content type of the response
319320
:ivar bool is_closed: Whether the network connection has been closed yet
320321
:ivar bool is_stream_consumed: When getting a stream response, checks

sdk/core/azure-core/azure/core/rest/_rest_py3.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -262,16 +262,18 @@ def encoding(self) -> Optional[str]:
262262
def encoding(self, value: str) -> None:
263263
"""Sets the response encoding"""
264264
self._encoding = value
265+
self._text = None # clear text cache
265266

266-
@property
267-
def text(self) -> str:
268-
"""Returns the response body as a string"""
269-
if self._text is None:
270-
content = self.content
271-
if not content:
272-
self._text = ""
273-
else:
274-
self._text = decode_to_text(self.encoding, self.content)
267+
def text(self, encoding: Optional[str] = None) -> str:
268+
"""Returns the response body as a string
269+
270+
:param optional[str] encoding: The encoding you want to decode the text with. Can
271+
also be set independently through our encoding property
272+
:return: The response's content decoded as a string.
273+
"""
274+
if self._text is None or encoding:
275+
encoding_to_pass = encoding or self.encoding
276+
self._text = decode_to_text(encoding_to_pass, self.content)
275277
return self._text
276278

277279
def json(self) -> Any:
@@ -284,7 +286,7 @@ def json(self) -> Any:
284286
# this will trigger errors if response is not read in
285287
self.content # pylint: disable=pointless-statement
286288
if not self._json:
287-
self._json = loads(self.text)
289+
self._json = loads(self.text())
288290
return self._json
289291

290292
def raise_for_status(self) -> None:
@@ -328,7 +330,6 @@ class HttpResponse(_HttpResponseBase):
328330
:ivar str text: The response body as a string.
329331
:ivar request: The request that resulted in this response.
330332
:vartype request: ~azure.core.rest.HttpRequest
331-
:ivar internal_response: The object returned from the HTTP library.
332333
:ivar str content_type: The content type of the response
333334
:ivar bool is_closed: Whether the network connection has been closed yet
334335
:ivar bool is_stream_consumed: When getting a stream response, checks
@@ -421,7 +422,6 @@ class AsyncHttpResponse(_HttpResponseBase):
421422
422423
:keyword request: The request that resulted in this response.
423424
:paramtype request: ~azure.core.rest.HttpRequest
424-
:keyword internal_response: The object returned from the HTTP library.
425425
:ivar int status_code: The status code of this response
426426
:ivar mapping headers: The response headers
427427
:ivar str reason: The reason phrase for this response
@@ -432,7 +432,6 @@ class AsyncHttpResponse(_HttpResponseBase):
432432
:ivar str text: The response body as a string.
433433
:ivar request: The request that resulted in this response.
434434
:vartype request: ~azure.core.rest.HttpRequest
435-
:ivar internal_response: The object returned from the HTTP library.
436435
:ivar str content_type: The content type of the response
437436
:ivar bool is_closed: Whether the network connection has been closed yet
438437
:ivar bool is_stream_consumed: When getting a stream response, checks

sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_context_manager_async.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
async def test_normal_call(client):
1414
async def _raise_and_get_text(response):
1515
response.raise_for_status()
16-
assert response.text == "Hello, world!"
16+
assert response.text() == "Hello, world!"
1717
assert response.is_closed
1818
request = HttpRequest("GET", url="/basic/string")
1919
response = await client.send_request(request)
@@ -33,9 +33,9 @@ async def _raise_and_get_text(response):
3333
response.raise_for_status()
3434
assert not response.is_closed
3535
with pytest.raises(ResponseNotReadError):
36-
response.text
36+
response.text()
3737
await response.read()
38-
assert response.text == "Hello, world!"
38+
assert response.text() == "Hello, world!"
3939
assert response.is_closed
4040
request = HttpRequest("GET", url="/streams/basic")
4141
response = await client.send_request(request, stream=True)

sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
@pytest.fixture
1515
def send_request(client):
1616
async def _send_request(request):
17-
response = await client.send_request(request, stream=False)
18-
response.raise_for_status()
19-
return response
17+
async with client:
18+
response = await client.send_request(request, stream=False)
19+
response.raise_for_status()
20+
return response
2021
return _send_request
2122

2223
@pytest.mark.asyncio
@@ -27,7 +28,7 @@ async def test_response(send_request, port):
2728
assert response.status_code == 200
2829
assert response.reason == "OK"
2930
assert response.content == b"Hello, world!"
30-
assert response.text == "Hello, world!"
31+
assert response.text() == "Hello, world!"
3132
assert response.request.method == "GET"
3233
assert response.request.url == "http://localhost:{}/basic/string".format(port)
3334

@@ -40,7 +41,7 @@ async def test_response_content(send_request):
4041
assert response.reason == "OK"
4142
content = await response.read()
4243
assert content == b"Hello, world!"
43-
assert response.text == "Hello, world!"
44+
assert response.text() == "Hello, world!"
4445

4546
@pytest.mark.asyncio
4647
async def test_response_text(send_request):
@@ -51,7 +52,7 @@ async def test_response_text(send_request):
5152
assert response.reason == "OK"
5253
content = await response.read()
5354
assert content == b"Hello, world!"
54-
assert response.text == "Hello, world!"
55+
assert response.text() == "Hello, world!"
5556
assert response.headers["Content-Length"] == '13'
5657
assert response.headers['Content-Type'] == "text/plain; charset=utf-8"
5758

@@ -64,7 +65,7 @@ async def test_response_html(send_request):
6465
assert response.reason == "OK"
6566
content = await response.read()
6667
assert content == b"<html><body>Hello, world!</html></body>"
67-
assert response.text == "<html><body>Hello, world!</html></body>"
68+
assert response.text() == "<html><body>Hello, world!</html></body>"
6869

6970
@pytest.mark.asyncio
7071
async def test_raise_for_status(client):
@@ -106,7 +107,7 @@ async def test_response_content_type_encoding(send_request):
106107
await response.read()
107108
assert response.content_type == "text/plain; charset=latin-1"
108109
assert response.content == b'Latin 1: \xff'
109-
assert response.text == "Latin 1: ÿ"
110+
assert response.text() == "Latin 1: ÿ"
110111
assert response.encoding == "latin-1"
111112

112113

@@ -119,7 +120,7 @@ async def test_response_autodetect_encoding(send_request):
119120
request=HttpRequest("GET", "/encoding/latin-1")
120121
)
121122
await response.read()
122-
assert response.text == u'Latin 1: ÿ'
123+
assert response.text() == u'Latin 1: ÿ'
123124
assert response.encoding == "latin-1"
124125

125126

@@ -133,7 +134,7 @@ async def test_response_fallback_to_autodetect(send_request):
133134
)
134135
await response.read()
135136
assert response.headers["Content-Type"] == "text/plain; charset=invalid-codec-name"
136-
assert response.text == "おはようございます。"
137+
assert response.text() == "おはようございます。"
137138
assert response.encoding is None
138139

139140

@@ -152,20 +153,20 @@ async def test_response_no_charset_with_ascii_content(send_request):
152153
assert response.encoding is None
153154
content = await response.read()
154155
assert content == b"Hello, world!"
155-
assert response.text == "Hello, world!"
156+
assert response.text() == "Hello, world!"
156157

157158

158159
@pytest.mark.asyncio
159160
async def test_response_no_charset_with_iso_8859_1_content(send_request):
160161
"""
161-
A response with ISO 8859-1 encoded content should decode correctly,
162-
even with no charset specified.
162+
We don't support iso-8859-1 by default following conversations
163+
about endoding flow
163164
"""
164165
response = await send_request(
165166
request=HttpRequest("GET", "/encoding/iso-8859-1"),
166167
)
167168
await response.read()
168-
assert response.text == "Accented: �sterreich" # aiohttp is having diff behavior than requests
169+
assert response.text() == "Accented: �sterreich"
169170
assert response.encoding is None
170171

171172
# NOTE: aiohttp isn't liking this
@@ -177,7 +178,7 @@ async def test_response_no_charset_with_iso_8859_1_content(send_request):
177178
# assert response.headers["Content-Type"] == "text/plain; charset=utf-8"
178179
# response.encoding = "latin-1"
179180
# await response.read()
180-
# assert response.text == "Latin 1: ÿ"
181+
# assert response.text() == "Latin 1: ÿ"
181182
# assert response.encoding == "latin-1"
182183

183184
@pytest.mark.asyncio
@@ -204,23 +205,23 @@ async def test_emoji(send_request):
204205
request=HttpRequest("GET", "/encoding/emoji"),
205206
)
206207
await response.read()
207-
assert response.text == "👩"
208+
assert response.text() == "👩"
208209

209210
@pytest.mark.asyncio
210211
async def test_emoji_family_with_skin_tone_modifier(send_request):
211212
response = await send_request(
212213
request=HttpRequest("GET", "/encoding/emoji-family-skin-tone-modifier"),
213214
)
214215
await response.read()
215-
assert response.text == "👩🏻‍👩🏽‍👧🏾‍👦🏿 SSN: 859-98-0987"
216+
assert response.text() == "👩🏻‍👩🏽‍👧🏾‍👦🏿 SSN: 859-98-0987"
216217

217218
@pytest.mark.asyncio
218219
async def test_korean_nfc(send_request):
219220
response = await send_request(
220221
request=HttpRequest("GET", "/encoding/korean"),
221222
)
222223
await response.read()
223-
assert response.text == "아가"
224+
assert response.text() == "아가"
224225

225226
@pytest.mark.asyncio
226227
async def test_urlencoded_content(send_request):
@@ -249,9 +250,25 @@ async def test_send_request_return_pipeline_response(client):
249250
assert hasattr(response, "http_request")
250251
assert hasattr(response, "http_response")
251252
assert hasattr(response, "context")
252-
assert response.http_response.text == "Hello, world!"
253+
assert response.http_response.text() == "Hello, world!"
253254
assert hasattr(response.http_request, "content")
254255

256+
@pytest.mark.asyncio
257+
async def test_text_and_encoding(send_request):
258+
response = await send_request(
259+
request=HttpRequest("GET", "/encoding/emoji"),
260+
)
261+
assert response.content == u"👩".encode("utf-8")
262+
assert response.text() == u"👩"
263+
264+
# try setting encoding as a property
265+
response.encoding = "utf-16"
266+
assert response.text() == u"鿰ꦑ" == response.content.decode(response.encoding)
267+
268+
# assert latin-1 changes text decoding without changing encoding property
269+
assert response.text("latin-1") == \x9f\x91©' == response.content.decode("latin-1")
270+
assert response.encoding == "utf-16"
271+
255272
# @pytest.mark.asyncio
256273
# async def test_multipart_encode_non_seekable_filelike(send_request):
257274
# """

sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_stream_responses_async.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,11 @@ async def test_iter_read_back_and_forth(client):
170170
async for line in response.iter_lines():
171171
assert line
172172
with pytest.raises(ResponseNotReadError):
173-
response.text
173+
response.text()
174174
with pytest.raises(StreamConsumedError):
175175
await response.read()
176176
with pytest.raises(ResponseNotReadError):
177-
response.text
177+
response.text()
178178

179179
@pytest.mark.asyncio
180180
async def test_stream_with_return_pipeline_response(client):

0 commit comments

Comments
 (0)