From 07407a11cc5866227cce4e68d86e79e02e135458 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Mon, 16 Aug 2021 13:13:53 -0400 Subject: [PATCH 1/9] switch text from property to method and update existing tests --- .../azure/core/rest/_requests_basic.py | 5 ++-- sdk/core/azure-core/azure/core/rest/_rest.py | 20 ++++++++----- .../azure-core/azure/core/rest/_rest_py3.py | 18 +++++++---- .../test_rest_context_manager_async.py | 6 ++-- .../test_rest_http_response_async.py | 28 ++++++++--------- .../test_rest_stream_responses_async.py | 4 +-- .../test_rest_context_manager.py | 6 ++-- .../test_rest_http_response.py | 30 +++++++++---------- .../test_rest_stream_responses.py | 6 ++-- 9 files changed, 68 insertions(+), 55 deletions(-) diff --git a/sdk/core/azure-core/azure/core/rest/_requests_basic.py b/sdk/core/azure-core/azure/core/rest/_requests_basic.py index e8ef734e1275..773acb26bb76 100644 --- a/sdk/core/azure-core/azure/core/rest/_requests_basic.py +++ b/sdk/core/azure-core/azure/core/rest/_requests_basic.py @@ -85,10 +85,11 @@ def encoding(self, value): self._encoding = value self._internal_response.encoding = value - @property - def text(self): + def text(self, encoding=None): # this will trigger errors if response is not read in self.content # pylint: disable=pointless-statement + if encoding: + self._internal_response.encoding = encoding return self._internal_response.text def _stream_download_helper(decompress, response): diff --git a/sdk/core/azure-core/azure/core/rest/_rest.py b/sdk/core/azure-core/azure/core/rest/_rest.py index 295051a83c50..5cbad8e2668c 100644 --- a/sdk/core/azure-core/azure/core/rest/_rest.py +++ b/sdk/core/azure-core/azure/core/rest/_rest.py @@ -235,17 +235,23 @@ def encoding(self, value): # type: (str) -> None """Sets the response encoding""" self._encoding = value + self._text = None # clear text cache - @property - def text(self): - # type: (...) -> str - """Returns the response body as a string""" - if self._text is None: + def text(self, encoding=None): + # type: (Optional[str]) -> str + """Returns the response body as a string + + :param optional[str] encoding: The encoding you want to decode the text with. Can + also be set independently through our encoding property + :return: The response's content decoded as a string. + """ + if self._text is None or encoding: content = self.content if not content: self._text = "" else: - self._text = decode_to_text(self.encoding, self.content) + encoding_to_pass = encoding or self.encoding + self._text = decode_to_text(encoding_to_pass, self.content) return self._text def json(self): @@ -259,7 +265,7 @@ def json(self): # this will trigger errors if response is not read in self.content # pylint: disable=pointless-statement if not self._json: - self._json = loads(self.text) + self._json = loads(self.text()) return self._json def raise_for_status(self): diff --git a/sdk/core/azure-core/azure/core/rest/_rest_py3.py b/sdk/core/azure-core/azure/core/rest/_rest_py3.py index af957f767a39..53759160e861 100644 --- a/sdk/core/azure-core/azure/core/rest/_rest_py3.py +++ b/sdk/core/azure-core/azure/core/rest/_rest_py3.py @@ -262,16 +262,22 @@ def encoding(self) -> Optional[str]: def encoding(self, value: str) -> None: """Sets the response encoding""" self._encoding = value + self._text = None # clear text cache - @property - def text(self) -> str: - """Returns the response body as a string""" - if self._text is None: + def text(self, encoding: Optional[str] = None) -> str: + """Returns the response body as a string + + :param optional[str] encoding: The encoding you want to decode the text with. Can + also be set independently through our encoding property + :return: The response's content decoded as a string. + """ + if self._text is None or encoding: content = self.content if not content: self._text = "" else: - self._text = decode_to_text(self.encoding, self.content) + encoding_to_pass = encoding or self.encoding + self._text = decode_to_text(encoding_to_pass, self.content) return self._text def json(self) -> Any: @@ -284,7 +290,7 @@ def json(self) -> Any: # this will trigger errors if response is not read in self.content # pylint: disable=pointless-statement if not self._json: - self._json = loads(self.text) + self._json = loads(self.text()) return self._json def raise_for_status(self) -> None: diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_context_manager_async.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_context_manager_async.py index 4afcac42172f..70ca63685b84 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_context_manager_async.py +++ b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_context_manager_async.py @@ -13,7 +13,7 @@ async def test_normal_call(client): async def _raise_and_get_text(response): response.raise_for_status() - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" assert response.is_closed request = HttpRequest("GET", url="/basic/string") response = await client.send_request(request) @@ -33,9 +33,9 @@ async def _raise_and_get_text(response): response.raise_for_status() assert not response.is_closed with pytest.raises(ResponseNotReadError): - response.text + response.text() await response.read() - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" assert response.is_closed request = HttpRequest("GET", url="/streams/basic") response = await client.send_request(request, stream=True) diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py index 47286b76254b..0cb70e2cfaae 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py +++ b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py @@ -27,7 +27,7 @@ async def test_response(send_request, port): assert response.status_code == 200 assert response.reason == "OK" assert response.content == b"Hello, world!" - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" assert response.request.method == "GET" assert response.request.url == "http://localhost:{}/basic/string".format(port) @@ -40,7 +40,7 @@ async def test_response_content(send_request): assert response.reason == "OK" content = await response.read() assert content == b"Hello, world!" - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" @pytest.mark.asyncio async def test_response_text(send_request): @@ -51,7 +51,7 @@ async def test_response_text(send_request): assert response.reason == "OK" content = await response.read() assert content == b"Hello, world!" - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" assert response.headers["Content-Length"] == '13' assert response.headers['Content-Type'] == "text/plain; charset=utf-8" @@ -64,7 +64,7 @@ async def test_response_html(send_request): assert response.reason == "OK" content = await response.read() assert content == b"Hello, world!" - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" @pytest.mark.asyncio async def test_raise_for_status(client): @@ -106,7 +106,7 @@ async def test_response_content_type_encoding(send_request): await response.read() assert response.content_type == "text/plain; charset=latin-1" assert response.content == b'Latin 1: \xff' - assert response.text == "Latin 1: ÿ" + assert response.text() == "Latin 1: ÿ" assert response.encoding == "latin-1" @@ -119,7 +119,7 @@ async def test_response_autodetect_encoding(send_request): request=HttpRequest("GET", "/encoding/latin-1") ) await response.read() - assert response.text == u'Latin 1: ÿ' + assert response.text() == u'Latin 1: ÿ' assert response.encoding == "latin-1" @@ -133,7 +133,7 @@ async def test_response_fallback_to_autodetect(send_request): ) await response.read() assert response.headers["Content-Type"] == "text/plain; charset=invalid-codec-name" - assert response.text == "おはようございます。" + assert response.text() == "おはようございます。" assert response.encoding is None @@ -152,7 +152,7 @@ async def test_response_no_charset_with_ascii_content(send_request): assert response.encoding is None content = await response.read() assert content == b"Hello, world!" - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" @pytest.mark.asyncio @@ -165,7 +165,7 @@ async def test_response_no_charset_with_iso_8859_1_content(send_request): request=HttpRequest("GET", "/encoding/iso-8859-1"), ) await response.read() - assert response.text == "Accented: �sterreich" # aiohttp is having diff behavior than requests + assert response.text() == "Accented: �sterreich" # aiohttp is having diff behavior than requests assert response.encoding is None # NOTE: aiohttp isn't liking this @@ -177,7 +177,7 @@ async def test_response_no_charset_with_iso_8859_1_content(send_request): # assert response.headers["Content-Type"] == "text/plain; charset=utf-8" # response.encoding = "latin-1" # await response.read() -# assert response.text == "Latin 1: ÿ" +# assert response.text() == "Latin 1: ÿ" # assert response.encoding == "latin-1" @pytest.mark.asyncio @@ -204,7 +204,7 @@ async def test_emoji(send_request): request=HttpRequest("GET", "/encoding/emoji"), ) await response.read() - assert response.text == "👩" + assert response.text() == "👩" @pytest.mark.asyncio async def test_emoji_family_with_skin_tone_modifier(send_request): @@ -212,7 +212,7 @@ async def test_emoji_family_with_skin_tone_modifier(send_request): request=HttpRequest("GET", "/encoding/emoji-family-skin-tone-modifier"), ) await response.read() - assert response.text == "👩🏻‍👩🏽‍👧🏾‍👦🏿 SSN: 859-98-0987" + assert response.text() == "👩🏻‍👩🏽‍👧🏾‍👦🏿 SSN: 859-98-0987" @pytest.mark.asyncio async def test_korean_nfc(send_request): @@ -220,7 +220,7 @@ async def test_korean_nfc(send_request): request=HttpRequest("GET", "/encoding/korean"), ) await response.read() - assert response.text == "아가" + assert response.text() == "아가" @pytest.mark.asyncio async def test_urlencoded_content(send_request): @@ -249,7 +249,7 @@ async def test_send_request_return_pipeline_response(client): assert hasattr(response, "http_request") assert hasattr(response, "http_response") assert hasattr(response, "context") - assert response.http_response.text == "Hello, world!" + assert response.http_response.text() == "Hello, world!" assert hasattr(response.http_request, "content") # @pytest.mark.asyncio diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_stream_responses_async.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_stream_responses_async.py index 673148749719..19cd093222e1 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_stream_responses_async.py +++ b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_stream_responses_async.py @@ -170,11 +170,11 @@ async def test_iter_read_back_and_forth(client): async for line in response.iter_lines(): assert line with pytest.raises(ResponseNotReadError): - response.text + response.text() with pytest.raises(StreamConsumedError): await response.read() with pytest.raises(ResponseNotReadError): - response.text + response.text() @pytest.mark.asyncio async def test_stream_with_return_pipeline_response(client): diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_context_manager.py b/sdk/core/azure-core/tests/testserver_tests/test_rest_context_manager.py index 34f802971537..0531cfe1505c 100644 --- a/sdk/core/azure-core/tests/testserver_tests/test_rest_context_manager.py +++ b/sdk/core/azure-core/tests/testserver_tests/test_rest_context_manager.py @@ -11,7 +11,7 @@ def test_normal_call(client, port): def _raise_and_get_text(response): response.raise_for_status() - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" assert response.is_closed request = HttpRequest("GET", url="/basic/string") response = client.send_request(request) @@ -30,9 +30,9 @@ def _raise_and_get_text(response): response.raise_for_status() assert not response.is_closed with pytest.raises(ResponseNotReadError): - response.text + response.text() response.read() - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" assert response.is_closed request = HttpRequest("GET", url="/streams/basic") response = client.send_request(request, stream=True) diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py b/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py index 804a98b8890e..aefa7e1e1974 100644 --- a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py +++ b/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py @@ -29,7 +29,7 @@ def test_response(send_request, port): ) assert response.status_code == 200 assert response.reason == "OK" - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" assert response.request.method == "GET" assert response.request.url == "http://localhost:{}/basic/string".format(port) @@ -40,7 +40,7 @@ def test_response_content(send_request): ) assert response.status_code == 200 assert response.reason == "OK" - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" def test_response_text(send_request): @@ -49,7 +49,7 @@ def test_response_text(send_request): ) assert response.status_code == 200 assert response.reason == "OK" - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" assert response.headers["Content-Length"] == '13' assert response.headers['Content-Type'] == "text/plain; charset=utf-8" assert response.content_type == "text/plain; charset=utf-8" @@ -60,7 +60,7 @@ def test_response_html(send_request): ) assert response.status_code == 200 assert response.reason == "OK" - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" def test_raise_for_status(client): response = client.send_request( @@ -97,7 +97,7 @@ def test_response_content_type_encoding(send_request): request=HttpRequest("GET", "/encoding/latin-1") ) assert response.content_type == "text/plain; charset=latin-1" - assert response.text == u"Latin 1: ÿ" + assert response.text() == u"Latin 1: ÿ" assert response.encoding == "latin-1" @@ -109,7 +109,7 @@ def test_response_autodetect_encoding(send_request): request=HttpRequest("GET", "/encoding/latin-1") ) - assert response.text == u'Latin 1: ÿ' + assert response.text() == u'Latin 1: ÿ' assert response.encoding == "latin-1" @pytest.mark.skipif(sys.version_info < (3, 0), @@ -123,7 +123,7 @@ def test_response_fallback_to_autodetect(send_request): ) assert response.headers["Content-Type"] == "text/plain; charset=invalid-codec-name" - assert response.text == u"おはようございます。" + assert response.text() == u"おはようございます。" assert response.encoding is None @@ -139,7 +139,7 @@ def test_response_no_charset_with_ascii_content(send_request): assert response.headers["Content-Type"] == "text/plain" assert response.status_code == 200 assert response.encoding is None - assert response.text == "Hello, world!" + assert response.text() == "Hello, world!" def test_response_no_charset_with_iso_8859_1_content(send_request): @@ -150,7 +150,7 @@ def test_response_no_charset_with_iso_8859_1_content(send_request): response = send_request( request=HttpRequest("GET", "/encoding/iso-8859-1"), ) - assert response.text == u"Accented: Österreich" + assert response.text() == u"Accented: Österreich" assert response.encoding is None def test_response_set_explicit_encoding(send_request): @@ -160,7 +160,7 @@ def test_response_set_explicit_encoding(send_request): ) assert response.headers["Content-Type"] == "text/plain; charset=utf-8" response.encoding = "latin-1" - assert response.text == u"Latin 1: ÿ" + assert response.text() == u"Latin 1: ÿ" assert response.encoding == "latin-1" def test_json(send_request): @@ -181,19 +181,19 @@ def test_emoji(send_request): response = send_request( request=HttpRequest("GET", "/encoding/emoji"), ) - assert response.text == u"👩" + assert response.text() == u"👩" def test_emoji_family_with_skin_tone_modifier(send_request): response = send_request( request=HttpRequest("GET", "/encoding/emoji-family-skin-tone-modifier"), ) - assert response.text == u"👩🏻‍👩🏽‍👧🏾‍👦🏿 SSN: 859-98-0987" + assert response.text() == u"👩🏻‍👩🏽‍👧🏾‍👦🏿 SSN: 859-98-0987" def test_korean_nfc(send_request): response = send_request( request=HttpRequest("GET", "/encoding/korean"), ) - assert response.text == u"아가" + assert response.text() == u"아가" def test_urlencoded_content(send_request): send_request( @@ -255,7 +255,7 @@ def test_get_xml_basic(send_request): "/xml/basic", ) response = send_request(request) - parsed_xml = ET.fromstring(response.text) + parsed_xml = ET.fromstring(response.text()) assert parsed_xml.tag == 'slideshow' attributes = parsed_xml.attrib assert attributes['title'] == "Sample Slide Show" @@ -294,5 +294,5 @@ def test_send_request_return_pipeline_response(client): assert hasattr(response, "http_request") assert hasattr(response, "http_response") assert hasattr(response, "context") - assert response.http_response.text == "Hello, world!" + assert response.http_response.text() == "Hello, world!" assert hasattr(response.http_request, "content") diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_stream_responses.py b/sdk/core/azure-core/tests/testserver_tests/test_rest_stream_responses.py index 61053ca7abb9..cf547d8f750e 100644 --- a/sdk/core/azure-core/tests/testserver_tests/test_rest_stream_responses.py +++ b/sdk/core/azure-core/tests/testserver_tests/test_rest_stream_responses.py @@ -187,7 +187,7 @@ def test_iter_read(client): iterator = response.iter_lines() for line in iterator: assert line - assert response.text + assert response.text() def test_iter_read_back_and_forth(client): # thanks to McCoy Patiño for this test! @@ -202,11 +202,11 @@ def test_iter_read_back_and_forth(client): for line in iterator: assert line with pytest.raises(ResponseNotReadError): - response.text + response.text() with pytest.raises(StreamConsumedError): response.read() with pytest.raises(ResponseNotReadError): - response.text + response.text() def test_stream_with_return_pipeline_response(client): request = HttpRequest("GET", "/basic/lines") From f17bca04ee912f96bf2541f7ace4cd49fc608062 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Mon, 16 Aug 2021 13:32:04 -0400 Subject: [PATCH 2/9] add text and encoding tests --- .../test_rest_http_response_async.py | 23 ++++++++++++++++--- .../test_rest_http_response.py | 15 ++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py index 0cb70e2cfaae..ce1b3de18142 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py +++ b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py @@ -14,9 +14,10 @@ @pytest.fixture def send_request(client): async def _send_request(request): - response = await client.send_request(request, stream=False) - response.raise_for_status() - return response + async with client: + response = await client.send_request(request, stream=False) + response.raise_for_status() + return response return _send_request @pytest.mark.asyncio @@ -252,6 +253,22 @@ async def test_send_request_return_pipeline_response(client): assert response.http_response.text() == "Hello, world!" assert hasattr(response.http_request, "content") +@pytest.mark.asyncio +async def test_text_and_encoding(send_request): + response = await send_request( + request=HttpRequest("GET", "/encoding/emoji"), + ) + assert response.content == u"👩".encode("utf-8") + assert response.text() == u"👩" + + # try setting encoding as a property + response.encoding = "utf-16" + assert response.text() == u"鿰ꦑ" == response.content.decode(response.encoding) + + # assert latin-1 changes text decoding without changing encoding property + assert response.text("latin-1") == 'ð\x9f\x91©' == response.content.decode("latin-1") + assert response.encoding == "utf-16" + # @pytest.mark.asyncio # async def test_multipart_encode_non_seekable_filelike(send_request): # """ diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py b/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py index aefa7e1e1974..fe09a761fc07 100644 --- a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py +++ b/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py @@ -296,3 +296,18 @@ def test_send_request_return_pipeline_response(client): assert hasattr(response, "context") assert response.http_response.text() == "Hello, world!" assert hasattr(response.http_request, "content") + +def test_text_and_encoding(send_request): + response = send_request( + request=HttpRequest("GET", "/encoding/emoji"), + ) + assert response.content == u"👩".encode("utf-8") + assert response.text() == u"👩" + + # try setting encoding as a property + response.encoding = "utf-16" + assert response.text() == u"鿰ꦑ" == response.content.decode(response.encoding) + + # assert latin-1 changes text decoding without changing encoding property + assert response.text("latin-1") == 'ð\x9f\x91©' == response.content.decode("latin-1") + assert response.encoding == "utf-16" From 2160e4d7ecf60080b93bbb66b0e74fd434c1a0ca Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Mon, 16 Aug 2021 13:32:58 -0400 Subject: [PATCH 3/9] remove internal_response docstrings --- sdk/core/azure-core/azure/core/rest/_rest.py | 1 - sdk/core/azure-core/azure/core/rest/_rest_py3.py | 3 --- 2 files changed, 4 deletions(-) diff --git a/sdk/core/azure-core/azure/core/rest/_rest.py b/sdk/core/azure-core/azure/core/rest/_rest.py index 5cbad8e2668c..3dad9e65e796 100644 --- a/sdk/core/azure-core/azure/core/rest/_rest.py +++ b/sdk/core/azure-core/azure/core/rest/_rest.py @@ -320,7 +320,6 @@ class HttpResponse(_HttpResponseBase): # pylint: disable=too-many-instance-attr :ivar str text: The response body as a string. :ivar request: The request that resulted in this response. :vartype request: ~azure.core.rest.HttpRequest - :ivar internal_response: The object returned from the HTTP library. :ivar str content_type: The content type of the response :ivar bool is_closed: Whether the network connection has been closed yet :ivar bool is_stream_consumed: When getting a stream response, checks diff --git a/sdk/core/azure-core/azure/core/rest/_rest_py3.py b/sdk/core/azure-core/azure/core/rest/_rest_py3.py index 53759160e861..8b36b4f2a1be 100644 --- a/sdk/core/azure-core/azure/core/rest/_rest_py3.py +++ b/sdk/core/azure-core/azure/core/rest/_rest_py3.py @@ -334,7 +334,6 @@ class HttpResponse(_HttpResponseBase): :ivar str text: The response body as a string. :ivar request: The request that resulted in this response. :vartype request: ~azure.core.rest.HttpRequest - :ivar internal_response: The object returned from the HTTP library. :ivar str content_type: The content type of the response :ivar bool is_closed: Whether the network connection has been closed yet :ivar bool is_stream_consumed: When getting a stream response, checks @@ -427,7 +426,6 @@ class AsyncHttpResponse(_HttpResponseBase): :keyword request: The request that resulted in this response. :paramtype request: ~azure.core.rest.HttpRequest - :keyword internal_response: The object returned from the HTTP library. :ivar int status_code: The status code of this response :ivar mapping headers: The response headers :ivar str reason: The reason phrase for this response @@ -438,7 +436,6 @@ class AsyncHttpResponse(_HttpResponseBase): :ivar str text: The response body as a string. :ivar request: The request that resulted in this response. :vartype request: ~azure.core.rest.HttpRequest - :ivar internal_response: The object returned from the HTTP library. :ivar str content_type: The content type of the response :ivar bool is_closed: Whether the network connection has been closed yet :ivar bool is_stream_consumed: When getting a stream response, checks From e68f928db591e60d754502f036baa2eaf22e81ad Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Mon, 16 Aug 2021 14:13:42 -0400 Subject: [PATCH 4/9] remove redundant encoding code --- .../azure/core/rest/_requests_basic.py | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/sdk/core/azure-core/azure/core/rest/_requests_basic.py b/sdk/core/azure-core/azure/core/rest/_requests_basic.py index 773acb26bb76..84f1f8c7ea40 100644 --- a/sdk/core/azure-core/azure/core/rest/_requests_basic.py +++ b/sdk/core/azure-core/azure/core/rest/_requests_basic.py @@ -61,28 +61,10 @@ def content(self): # requests throws a RuntimeError if the content for a response is already consumed raise ResponseNotReadError(self) - @property - def encoding(self): - # type: () -> Optional[str] - retval = super(_RestRequestsTransportResponseBase, self).encoding - if not retval: - # There is a few situation where "requests" magic doesn't fit us: - # - https://github.com/psf/requests/issues/654 - # - https://github.com/psf/requests/issues/1737 - # - https://github.com/psf/requests/issues/2086 - from codecs import BOM_UTF8 - if self._internal_response.content[:3] == BOM_UTF8: - retval = "utf-8-sig" - if retval: - if retval == "utf-8": - retval = "utf-8-sig" - return retval - - @encoding.setter # type: ignore + @_HttpResponseBase.encoding.setter # type: ignore def encoding(self, value): # type: (str) -> None - # ignoring setter bc of known mypy issue https://github.com/python/mypy/issues/1465 - self._encoding = value + _HttpResponseBase.encoding.fset(self, value) self._internal_response.encoding = value def text(self, encoding=None): From 3541364ed94e7d5f6ca371f141a9597af1f7540c Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Mon, 16 Aug 2021 14:13:51 -0400 Subject: [PATCH 5/9] update changelog --- sdk/core/azure-core/CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sdk/core/azure-core/CHANGELOG.md b/sdk/core/azure-core/CHANGELOG.md index d9d8db2e1ada..16165e58c6ad 100644 --- a/sdk/core/azure-core/CHANGELOG.md +++ b/sdk/core/azure-core/CHANGELOG.md @@ -4,7 +4,10 @@ ### Features Added -### Breaking Changes +### Breaking Changes in the Provisional `azure.core.rest` package + +- The `text` property on `azure.core.rest.HttpResponse` and `azure.core.rest.AsyncHttpResponse` has changed to a method, which also takes +an `encoding` parameter. ### Bugs Fixed From 7e6f83d2f50f38d5bf6da02825c067bd92871e82 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Thu, 19 Aug 2021 11:51:52 -0400 Subject: [PATCH 6/9] unify text and encoding accross transports --- .../azure-core/azure/core/rest/_requests_basic.py | 13 ------------- .../async_tests/test_rest_http_response_async.py | 6 +++--- .../testserver_tests/test_rest_http_response.py | 6 +++--- 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/sdk/core/azure-core/azure/core/rest/_requests_basic.py b/sdk/core/azure-core/azure/core/rest/_requests_basic.py index 84f1f8c7ea40..bd83dc29bd39 100644 --- a/sdk/core/azure-core/azure/core/rest/_requests_basic.py +++ b/sdk/core/azure-core/azure/core/rest/_requests_basic.py @@ -61,19 +61,6 @@ def content(self): # requests throws a RuntimeError if the content for a response is already consumed raise ResponseNotReadError(self) - @_HttpResponseBase.encoding.setter # type: ignore - def encoding(self, value): - # type: (str) -> None - _HttpResponseBase.encoding.fset(self, value) - self._internal_response.encoding = value - - def text(self, encoding=None): - # this will trigger errors if response is not read in - self.content # pylint: disable=pointless-statement - if encoding: - self._internal_response.encoding = encoding - return self._internal_response.text - def _stream_download_helper(decompress, response): if response.is_stream_consumed: raise StreamConsumedError(response) diff --git a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py index ce1b3de18142..40587252a14f 100644 --- a/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py +++ b/sdk/core/azure-core/tests/testserver_tests/async_tests/test_rest_http_response_async.py @@ -159,14 +159,14 @@ async def test_response_no_charset_with_ascii_content(send_request): @pytest.mark.asyncio async def test_response_no_charset_with_iso_8859_1_content(send_request): """ - A response with ISO 8859-1 encoded content should decode correctly, - even with no charset specified. + We don't support iso-8859-1 by default following conversations + about endoding flow """ response = await send_request( request=HttpRequest("GET", "/encoding/iso-8859-1"), ) await response.read() - assert response.text() == "Accented: �sterreich" # aiohttp is having diff behavior than requests + assert response.text() == "Accented: �sterreich" assert response.encoding is None # NOTE: aiohttp isn't liking this diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py b/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py index fe09a761fc07..5ff6d65bb80d 100644 --- a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py +++ b/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py @@ -144,13 +144,13 @@ def test_response_no_charset_with_ascii_content(send_request): def test_response_no_charset_with_iso_8859_1_content(send_request): """ - A response with ISO 8859-1 encoded content should decode correctly, - even with no charset specified. + We don't support iso-8859-1 by default following conversations + about endoding flow """ response = send_request( request=HttpRequest("GET", "/encoding/iso-8859-1"), ) - assert response.text() == u"Accented: Österreich" + assert response.text() == u"Accented: �sterreich" assert response.encoding is None def test_response_set_explicit_encoding(send_request): From bc467267e8f14fcdd6860977340ddd04f58d85f2 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Thu, 19 Aug 2021 13:09:41 -0400 Subject: [PATCH 7/9] convert to unicode str --- .../tests/testserver_tests/test_rest_http_response.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py b/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py index 5ff6d65bb80d..f3abec23a30a 100644 --- a/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py +++ b/sdk/core/azure-core/tests/testserver_tests/test_rest_http_response.py @@ -309,5 +309,5 @@ def test_text_and_encoding(send_request): assert response.text() == u"鿰ꦑ" == response.content.decode(response.encoding) # assert latin-1 changes text decoding without changing encoding property - assert response.text("latin-1") == 'ð\x9f\x91©' == response.content.decode("latin-1") + assert response.text("latin-1") == u'ð\x9f\x91©' == response.content.decode("latin-1") assert response.encoding == "utf-16" From 62a8e5c1393f9bb916b350fb7295c9acafad3f71 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Thu, 19 Aug 2021 13:20:13 -0400 Subject: [PATCH 8/9] remove unnecessary content setting --- sdk/core/azure-core/azure/core/rest/_rest.py | 3 +-- sdk/core/azure-core/azure/core/rest/_rest_py3.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sdk/core/azure-core/azure/core/rest/_rest.py b/sdk/core/azure-core/azure/core/rest/_rest.py index 3dad9e65e796..fc1258516d05 100644 --- a/sdk/core/azure-core/azure/core/rest/_rest.py +++ b/sdk/core/azure-core/azure/core/rest/_rest.py @@ -246,8 +246,7 @@ def text(self, encoding=None): :return: The response's content decoded as a string. """ if self._text is None or encoding: - content = self.content - if not content: + if not self.content: self._text = "" else: encoding_to_pass = encoding or self.encoding diff --git a/sdk/core/azure-core/azure/core/rest/_rest_py3.py b/sdk/core/azure-core/azure/core/rest/_rest_py3.py index 8b36b4f2a1be..a558aabb9465 100644 --- a/sdk/core/azure-core/azure/core/rest/_rest_py3.py +++ b/sdk/core/azure-core/azure/core/rest/_rest_py3.py @@ -272,8 +272,7 @@ def text(self, encoding: Optional[str] = None) -> str: :return: The response's content decoded as a string. """ if self._text is None or encoding: - content = self.content - if not content: + if not self.content: self._text = "" else: encoding_to_pass = encoding or self.encoding From 59fc8d5c774b6988935b4c3b459bc9a949a96f03 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Thu, 19 Aug 2021 13:53:46 -0400 Subject: [PATCH 9/9] remove unnecessary if else statement --- sdk/core/azure-core/azure/core/rest/_helpers.py | 2 ++ sdk/core/azure-core/azure/core/rest/_rest.py | 7 ++----- sdk/core/azure-core/azure/core/rest/_rest_py3.py | 7 ++----- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/sdk/core/azure-core/azure/core/rest/_helpers.py b/sdk/core/azure-core/azure/core/rest/_helpers.py index 4975d09d655c..a2f8736dcc68 100644 --- a/sdk/core/azure-core/azure/core/rest/_helpers.py +++ b/sdk/core/azure-core/azure/core/rest/_helpers.py @@ -293,6 +293,8 @@ def get_charset_encoding(response): def decode_to_text(encoding, content): # type: (Optional[str], bytes) -> str + if not content: + return "" if encoding == "utf-8": encoding = "utf-8-sig" if encoding: diff --git a/sdk/core/azure-core/azure/core/rest/_rest.py b/sdk/core/azure-core/azure/core/rest/_rest.py index fc1258516d05..10a8486a2c64 100644 --- a/sdk/core/azure-core/azure/core/rest/_rest.py +++ b/sdk/core/azure-core/azure/core/rest/_rest.py @@ -246,11 +246,8 @@ def text(self, encoding=None): :return: The response's content decoded as a string. """ if self._text is None or encoding: - if not self.content: - self._text = "" - else: - encoding_to_pass = encoding or self.encoding - self._text = decode_to_text(encoding_to_pass, self.content) + encoding_to_pass = encoding or self.encoding + self._text = decode_to_text(encoding_to_pass, self.content) return self._text def json(self): diff --git a/sdk/core/azure-core/azure/core/rest/_rest_py3.py b/sdk/core/azure-core/azure/core/rest/_rest_py3.py index a558aabb9465..21e42f46b044 100644 --- a/sdk/core/azure-core/azure/core/rest/_rest_py3.py +++ b/sdk/core/azure-core/azure/core/rest/_rest_py3.py @@ -272,11 +272,8 @@ def text(self, encoding: Optional[str] = None) -> str: :return: The response's content decoded as a string. """ if self._text is None or encoding: - if not self.content: - self._text = "" - else: - encoding_to_pass = encoding or self.encoding - self._text = decode_to_text(encoding_to_pass, self.content) + encoding_to_pass = encoding or self.encoding + self._text = decode_to_text(encoding_to_pass, self.content) return self._text def json(self) -> Any: