Skip to content

Commit

Permalink
feat(BaseService): support stream=True in BaseService.send()
Browse files Browse the repository at this point in the history
Fixes: arf/planning-sdk-squad/issues/901

This change allows generated operation code to pass 'stream=True' to
the BaseService.send() method, which will in turn pass it on to the
underlying requests.request() method.  The net result is that
the response body (even if it is a JSON object) will be "streamed",
which means it will be made available via the requests.Response object
rather than consumed and set on the DetailedResponse object.
To access the streamed response, simply retrieve the requests.Response
object by calling DetailedResponse.get_result(), then use the "iter_content"
method on the returned requests.Response instance.
  • Loading branch information
padamstx committed Jun 15, 2020
1 parent 7c6ad8b commit bf4179b
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
5 changes: 5 additions & 0 deletions ibm_cloud_sdk_core/base_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,18 @@ def send(self, request: requests.Request, **kwargs) -> DetailedResponse:
if self.disable_ssl_verification:
kwargs['verify'] = False

# Check to see if the caller specified the 'stream' argument.
stream_response = kwargs.get('stream') or False

try:
response = requests.request(**request, cookies=self.jar, **kwargs)

if 200 <= response.status_code <= 299:
if response.status_code == 204 or request['method'] == 'HEAD':
# There is no body content for a HEAD request or a 204 response
result = None
elif stream_response:
result = response
elif not response.text:
result = None
else:
Expand Down
47 changes: 47 additions & 0 deletions test/test_base_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import Optional
import pytest
import responses
import requests
import jwt
from ibm_cloud_sdk_core import BaseService, DetailedResponse
from ibm_cloud_sdk_core import ApiException
Expand Down Expand Up @@ -80,6 +81,13 @@ def head_request(self) -> DetailedResponse:
response = self.send(request)
return response

def get_document_as_stream(self) -> DetailedResponse:
params = {'version': self.version}
url = '/v1/streamjson'
request = self.prepare_request(method='GET', url=url, params=params)
response = self.send(request, stream=True)
return response


def get_access_token() -> str:
access_token_layout = {
Expand Down Expand Up @@ -135,6 +143,45 @@ def test_url_encoding():
assert 'version=2017-07-07' in responses.calls[0].request.url


@responses.activate
def test_stream_json_response():
service = AnyServiceV1('2017-07-07', authenticator=NoAuthAuthenticator())

path = '/v1/streamjson'
test_url = service.default_url + path

expected_response = json.dumps({"id": 1, "rev": "v1", "content": "this is a document"})

# print("Expected response: ", expected_response)

# Simulate a JSON response
responses.add(
responses.GET,
test_url,
status=200,
body=expected_response,
content_type='application/json')

# Invoke the operation and receive an "iterable" as the response
response = service.get_document_as_stream()

assert response is not None
assert len(responses.calls) == 1

# retrieve the requests.Response object from the DetailedResponse
resp = response.get_result()
assert isinstance(resp, requests.Response)
assert hasattr(resp, "iter_content")

# Retrieve the response body, one chunk at a time.
actual_response = ''
for chunk in resp.iter_content(chunk_size=3):
actual_response += chunk.decode("utf-8")

# print("Actual response: ", actual_response)
assert actual_response == expected_response


@responses.activate
def test_http_config():
service = AnyServiceV1('2017-07-07', authenticator=NoAuthAuthenticator())
Expand Down

0 comments on commit bf4179b

Please sign in to comment.