Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rest] have pipelines switch over to rest #20415

Closed
wants to merge 63 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
1289bbb
add HttpClientTransportResponse
iscai-msft Aug 3, 2021
3d85f54
add backcompat mixins
iscai-msft Aug 3, 2021
19b70c4
add tests
iscai-msft Aug 3, 2021
7671913
add tests
iscai-msft Aug 10, 2021
8d0345c
add support for aiohttp and comma separated values
iscai-msft Aug 11, 2021
cfb98d1
remove My from class extension names
iscai-msft Aug 11, 2021
f2a1b17
address PR comments
iscai-msft Aug 16, 2021
07407a1
switch text from property to method and update existing tests
iscai-msft Aug 16, 2021
f17bca0
add text and encoding tests
iscai-msft Aug 16, 2021
2160e4d
remove internal_response docstrings
iscai-msft Aug 16, 2021
e68f928
remove redundant encoding code
iscai-msft Aug 16, 2021
3541364
update changelog
iscai-msft Aug 16, 2021
a028a23
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-python …
iscai-msft Aug 17, 2021
9b64244
Merge branch 'test_to_function' of https://github.com/iscai-msft/azur…
iscai-msft Aug 17, 2021
78b02b1
temp
iscai-msft Aug 17, 2021
365fa47
change default get behavior and add tests to sync test suite
iscai-msft Aug 17, 2021
c6ec359
temp
iscai-msft Aug 18, 2021
54e92a4
fix aiohttp kyes and values to be mutable
iscai-msft Aug 19, 2021
7e6f83d
unify text and encoding accross transports
iscai-msft Aug 19, 2021
bc46726
convert to unicode str
iscai-msft Aug 19, 2021
62a8e5c
remove unnecessary content setting
iscai-msft Aug 19, 2021
59fc8d5
remove unnecessary if else statement
iscai-msft Aug 19, 2021
a282493
Merge branch 'test_to_function' of https://github.com/iscai-msft/azur…
iscai-msft Aug 19, 2021
8bbcd98
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-python …
iscai-msft Aug 20, 2021
f7fa1e0
temp
iscai-msft Aug 20, 2021
a03a9a7
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-python …
iscai-msft Aug 23, 2021
4616424
temp
iscai-msft Aug 23, 2021
ea06e45
make 2.7 compatible
iscai-msft Aug 23, 2021
5c593b9
Merge branch 'header_tuples' of https://github.com/Azure/azure-sdk-fo…
iscai-msft Aug 23, 2021
28ef142
revert tests
iscai-msft Aug 23, 2021
622539a
fix mypy
iscai-msft Aug 23, 2021
9d7bc15
Merge branch 'header_tuples' of https://github.com/Azure/azure-sdk-fo…
iscai-msft Aug 23, 2021
2f60925
current tests passing
iscai-msft Aug 23, 2021
523544a
move pipeline transport responses into pipeline transport folder
iscai-msft Aug 23, 2021
c0b41ba
run tests against pipeline tranposrt and rest
iscai-msft Aug 24, 2021
3259966
lint and mypy
iscai-msft Aug 25, 2021
329d01b
ignore backcompat properties
iscai-msft Aug 25, 2021
c71823c
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-python …
iscai-msft Aug 25, 2021
6b8f092
fix changelog
iscai-msft Aug 25, 2021
082d1ae
remove headers documentation from changelog
iscai-msft Aug 25, 2021
008bd8c
improve diff
iscai-msft Aug 25, 2021
bbdcccc
fix typing for async iterator
iscai-msft Aug 25, 2021
56f65eb
use getattr and setattr to hide properties
iscai-msft Aug 25, 2021
810baa3
add deprecated docstrings
iscai-msft Aug 25, 2021
ac1bdd2
try fixing reading
iscai-msft Aug 25, 2021
5309fa9
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-python …
iscai-msft Aug 25, 2021
8be7efe
stop aiohttp timeout
iscai-msft Aug 26, 2021
597710b
lint
iscai-msft Aug 26, 2021
9e40b35
fix stream_download
iscai-msft Aug 26, 2021
dd179c7
fix getattr in requests and getstate in aiohttp
iscai-msft Aug 26, 2021
c161fc7
add base polling tests
iscai-msft Aug 26, 2021
48d46f2
mypy
iscai-msft Aug 26, 2021
a52920b
remove incorrect tests import
iscai-msft Aug 26, 2021
11338f4
read in response if necessary in deserialize_from_http_generics
iscai-msft Aug 27, 2021
7fb1e18
add read to httpclienttransportresponse
iscai-msft Aug 27, 2021
edab626
switch to protocol
iscai-msft Aug 27, 2021
c2157a5
update changelog
iscai-msft Aug 27, 2021
bdbbb6e
add initial tests
iscai-msft Aug 27, 2021
324f1ae
switch from protocol to abc
iscai-msft Aug 27, 2021
c8cc257
Merge branch 'switch_to_protocol' of https://github.com/iscai-msft/az…
iscai-msft Aug 29, 2021
9bb6c96
move impl to pipline transport file
iscai-msft Aug 30, 2021
bf53c04
temp
iscai-msft Aug 30, 2021
15b2619
temp
iscai-msft Aug 30, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions sdk/core/azure-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

- The `text` property on `azure.core.rest.HttpResponse` and `azure.core.rest.AsyncHttpResponse` has changed to a method, which also takes
an `encoding` parameter.
- `azure.core.rest.HttpResponse` and `azure.core.rest.AsyncHttpResponse` are now abstract base classes. They should not be initialized directly, instead
your transport responses should inherit from them and implement them.

### Bugs Fixed

Expand Down
31 changes: 3 additions & 28 deletions sdk/core/azure-core/azure/core/_pipeline_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
RequestIdPolicy,
RetryPolicy,
)
from .pipeline._tools import to_rest_response as _to_rest_response

try:
from typing import TYPE_CHECKING
Expand All @@ -65,17 +64,6 @@

_LOGGER = logging.getLogger(__name__)

def _prepare_request(request):
# returns the request ready to run through pipelines
# and a bool telling whether we ended up converting it
rest_request = False
try:
request_to_run = request._to_pipeline_transport_request() # pylint: disable=protected-access
rest_request = True
except AttributeError:
request_to_run = request
return rest_request, request_to_run

class PipelineClient(PipelineClientBase):
"""Service client core methods.

Expand Down Expand Up @@ -203,22 +191,9 @@ def send_request(self, request, **kwargs):
: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
# """
rest_request, request_to_run = _prepare_request(request)
"""
return_pipeline_response = kwargs.pop("_return_pipeline_response", False)
pipeline_response = self._pipeline.run(request_to_run, **kwargs) # pylint: disable=protected-access
response = pipeline_response.http_response
if rest_request:
response = _to_rest_response(response)
try:
if not kwargs.get("stream", False):
response.read()
response.close()
except Exception as exc:
response.close()
raise exc
pipeline_response = self._pipeline.run(request, **kwargs) # pylint: disable=protected-access
if return_pipeline_response:
pipeline_response.http_response = response
pipeline_response.http_request = request
return pipeline_response
return response
return pipeline_response.http_response
54 changes: 27 additions & 27 deletions sdk/core/azure-core/azure/core/_pipeline_client_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
# --------------------------------------------------------------------------

import logging
from collections.abc import Iterable
import collections.abc
from typing import Any, Awaitable
from .configuration import Configuration
from .pipeline import AsyncPipeline
Expand All @@ -37,8 +37,6 @@
RequestIdPolicy,
AsyncRetryPolicy,
)
from ._pipeline_client import _prepare_request
from .pipeline._tools_async import to_rest_response as _to_rest_response

try:
from typing import TYPE_CHECKING, TypeVar
Expand All @@ -63,6 +61,26 @@

_LOGGER = logging.getLogger(__name__)

class _AsyncContextManager(collections.abc.Awaitable):

def __init__(self, wrapped: collections.abc.Awaitable):
super().__init__()
self.wrapped = wrapped
self.response = None

def __await__(self):
return self.wrapped.__await__()

async def __aenter__(self):
self.response = await self
return self.response

async def __aexit__(self, *args):
await self.response.__aexit__(*args)

async def close(self):
await self.response.close()


class AsyncPipelineClient(PipelineClientBase):
"""Service client core methods.
Expand Down Expand Up @@ -126,7 +144,7 @@ def _build_pipeline(self, config, **kwargs): # pylint: disable=no-self-use
config.proxy_policy,
ContentDecodePolicy(**kwargs)
]
if isinstance(per_call_policies, Iterable):
if isinstance(per_call_policies, collections.abc.Iterable):
policies.extend(per_call_policies)
else:
policies.append(per_call_policies)
Expand All @@ -135,7 +153,7 @@ def _build_pipeline(self, config, **kwargs): # pylint: disable=no-self-use
config.retry_policy,
config.authentication_policy,
config.custom_hook_policy])
if isinstance(per_retry_policies, Iterable):
if isinstance(per_retry_policies, collections.abc.Iterable):
policies.extend(per_retry_policies)
else:
policies.append(per_retry_policies)
Expand All @@ -144,13 +162,13 @@ def _build_pipeline(self, config, **kwargs): # pylint: disable=no-self-use
DistributedTracingPolicy(**kwargs),
config.http_logging_policy or HttpLoggingPolicy(**kwargs)])
else:
if isinstance(per_call_policies, Iterable):
if isinstance(per_call_policies, collections.abc.Iterable):
per_call_policies_list = list(per_call_policies)
else:
per_call_policies_list = [per_call_policies]
per_call_policies_list.extend(policies)
policies = per_call_policies_list
if isinstance(per_retry_policies, Iterable):
if isinstance(per_retry_policies, collections.abc.Iterable):
per_retry_policies_list = list(per_retry_policies)
else:
per_retry_policies_list = [per_retry_policies]
Expand All @@ -175,30 +193,13 @@ def _build_pipeline(self, config, **kwargs): # pylint: disable=no-self-use
return AsyncPipeline(transport, policies)

async def _make_pipeline_call(self, request, **kwargs):
rest_request, request_to_run = _prepare_request(request)
return_pipeline_response = kwargs.pop("_return_pipeline_response", False)
pipeline_response = await self._pipeline.run(
request_to_run, **kwargs # pylint: disable=protected-access
request, **kwargs # pylint: disable=protected-access
)
response = pipeline_response.http_response
if rest_request:
rest_response = _to_rest_response(response)
if not kwargs.get("stream"):
try:
# in this case, the pipeline transport response already called .load_body(), so
# the body is loaded. instead of doing response.read(), going to set the body
# to the internal content
rest_response._content = response.body() # pylint: disable=protected-access
await rest_response.close()
except Exception as exc:
await rest_response.close()
raise exc
response = rest_response
if return_pipeline_response:
pipeline_response.http_response = response
pipeline_response.http_request = request
return pipeline_response
return response
return pipeline_response.http_response

def send_request(
self,
Expand All @@ -223,6 +224,5 @@ def send_request(
:return: The response of your network call. Does not do error handling on your response.
:rtype: ~azure.core.rest.AsyncHttpResponse
"""
from .rest._rest_py3 import _AsyncContextManager
wrapped = self._make_pipeline_call(request, stream=stream, **kwargs)
return _AsyncContextManager(wrapped=wrapped)
42 changes: 7 additions & 35 deletions sdk/core/azure-core/azure/core/pipeline/_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,39 +33,11 @@ def await_result(func, *args, **kwargs):
)
return result

def to_rest_request(pipeline_transport_request):
from ..rest import HttpRequest as RestHttpRequest
return RestHttpRequest(
method=pipeline_transport_request.method,
url=pipeline_transport_request.url,
headers=pipeline_transport_request.headers,
files=pipeline_transport_request.files,
data=pipeline_transport_request.data
)

def to_rest_response(pipeline_transport_response):
from .transport._requests_basic import RequestsTransportResponse
from ..rest._requests_basic import RestRequestsTransportResponse
from ..rest import HttpResponse
if isinstance(pipeline_transport_response, RequestsTransportResponse):
response_type = RestRequestsTransportResponse
else:
response_type = HttpResponse
response = response_type(
request=to_rest_request(pipeline_transport_response.request),
internal_response=pipeline_transport_response.internal_response,
)
response._connection_data_block_size = pipeline_transport_response.block_size # pylint: disable=protected-access
return response

def get_block_size(response):
try:
return response._connection_data_block_size # pylint: disable=protected-access
except AttributeError:
return response.block_size

def get_internal_response(response):
def read_in_response(response, is_stream_response):
try:
return response._internal_response # pylint: disable=protected-access
except AttributeError:
return response.internal_response
if not is_stream_response:
response.read()
response.close()
except Exception as exc:
response.close()
raise exc
41 changes: 8 additions & 33 deletions sdk/core/azure-core/azure/core/pipeline/_tools_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
# IN THE SOFTWARE.
#
# --------------------------------------------------------------------------
from ._tools import to_rest_request
from typing import Optional

async def await_result(func, *args, **kwargs):
"""If func returns an awaitable, await it."""
Expand All @@ -33,36 +33,11 @@ async def await_result(func, *args, **kwargs):
return await result # type: ignore
return result

def _get_response_type(pipeline_transport_response):
async def read_in_response(response, is_stream_response: Optional[bool]) -> None:
try:
from .transport import AioHttpTransportResponse
from ..rest._aiohttp import RestAioHttpTransportResponse
if isinstance(pipeline_transport_response, AioHttpTransportResponse):
return RestAioHttpTransportResponse
except ImportError:
pass
try:
from .transport import AsyncioRequestsTransportResponse
from ..rest._requests_asyncio import RestAsyncioRequestsTransportResponse
if isinstance(pipeline_transport_response, AsyncioRequestsTransportResponse):
return RestAsyncioRequestsTransportResponse
except ImportError:
pass
try:
from .transport import TrioRequestsTransportResponse
from ..rest._requests_trio import RestTrioRequestsTransportResponse
if isinstance(pipeline_transport_response, TrioRequestsTransportResponse):
return RestTrioRequestsTransportResponse
except ImportError:
pass
from ..rest import AsyncHttpResponse
return AsyncHttpResponse

def to_rest_response(pipeline_transport_response):
response_type = _get_response_type(pipeline_transport_response)
response = response_type(
request=to_rest_request(pipeline_transport_response.request),
internal_response=pipeline_transport_response.internal_response,
)
response._connection_data_block_size = pipeline_transport_response.block_size # pylint: disable=protected-access
return response
if not is_stream_response:
await response.read()
await response.close()
except Exception as exc:
await response.close()
raise exc
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,8 @@ def deserialize_from_http_generics(
mime_type = "application/json"

# Rely on transport implementation to give me "text()" decoded correctly
if hasattr(response, "read"):
response.read()
return cls.deserialize_from_text(response.text(encoding), mime_type, response=response)

def on_request(self, request):
Expand Down
Loading