def result( self, timeout=None, # type: typing.Optional[float] ): # type: (...) -> typing.Union[T, IncomingResponse, typing.Tuple[T, IncomingResponse]] """DEPRECATED: please use the `response()` method instead. Blocking call to wait for and return the unmarshalled swagger result. :param timeout: Number of seconds to wait for a response. Defaults to None which means wait indefinitely. :type timeout: float :return: Depends on the value of also_return_response sent in to the constructor. """ incoming_response = self._get_incoming_response(timeout) swagger_result = self._get_swagger_result(incoming_response) if self.operation is not None: swagger_result = typing.cast(T, swagger_result) if self.request_config.also_return_response: return swagger_result, incoming_response return swagger_result if 200 <= incoming_response.status_code < 300: return incoming_response raise make_http_exception(response=incoming_response)
def result(self, timeout=None): """Blocking call to wait for the HTTP response. :param timeout: Number of seconds to wait for a response. Defaults to None which means wait indefinitely. :type timeout: float :return: Depends on the value of also_return_response sent in to the constructor. """ inner_response = self.future.result(timeout=timeout) incoming_response = self.response_adapter(inner_response) if self.operation is not None: unmarshal_response(incoming_response, self.operation, self.response_callbacks) swagger_result = incoming_response.swagger_result if self.also_return_response: return swagger_result, incoming_response return swagger_result if 200 <= incoming_response.status_code < 300: return incoming_response raise make_http_exception(response=incoming_response)
def unmarshal_response(incoming_response, operation, response_callbacks=None): """So the http_client is finished with its part of processing the response. This hands the response over to bravado_core for validation and unmarshalling and then runs any response callbacks. On success, the swagger_result is available as ``incoming_response.swagger_result``. :type incoming_response: :class:`bravado_core.response.IncomingResponse` :type operation: :class:`bravado_core.operation.Operation` :type response_callbacks: list of callable. See bravado_core.client.REQUEST_OPTIONS_DEFAULTS. :raises: HTTPError - On 5XX status code, the HTTPError has minimal information. - On non-2XX status code with no matching response, the HTTPError contains a detailed error message. - On non-2XX status code with a matching response, the HTTPError contains the return value. """ response_callbacks = response_callbacks or [] try: raise_on_unexpected(incoming_response) incoming_response.swagger_result = unmarshal_response_inner( response=incoming_response, op=operation, ) except MatchingResponseNotFound as e: exception = make_http_exception(response=incoming_response, message=str(e)) six.reraise(type(exception), exception, sys.exc_info()[2]) finally: # Always run the callbacks regardless of success/failure for response_callback in response_callbacks: response_callback(incoming_response, operation) raise_on_expected(incoming_response)
def result( self, timeout=None, # type: typing.Optional[float] ): # type: (...) -> typing.Union[T, IncomingResponse, typing.Tuple[T, IncomingResponse]] """DEPRECATED: please use the `response()` method instead. Blocking call to wait for and return the unmarshalled swagger result. :param timeout: Number of seconds to wait for a response. Defaults to None which means wait indefinitely. :type timeout: float :return: Depends on the value of also_return_response sent in to the constructor. """ incoming_response = self._get_incoming_response(timeout) swagger_result = self._get_swagger_result(incoming_response) if self.operation is not None: if self.request_config.also_return_response: return swagger_result, incoming_response return swagger_result if 200 <= incoming_response.status_code < 300: return incoming_response raise make_http_exception(response=incoming_response)
def raise_on_unexpected(http_response): """Raise an HTTPError if the response is 5XX. :param http_response: :class:`bravado_core.response.IncomingResponse` :raises: HTTPError """ if 500 <= http_response.status_code <= 599: raise make_http_exception(response=http_response)
def test_make_http_exception_unknown(): requests_response = Response() requests_response.status_code = 600 requests_response.reason = "Womp Error" exc = make_http_exception( RequestsResponseAdapter(requests_response), ) assert type(exc) == HTTPError
def test_make_http_exception(response_500): incoming_response = RequestsResponseAdapter(response_500) exc = make_http_exception(incoming_response, message="Holy moly!", swagger_result={'msg': 'Kaboom'}) assert isinstance(exc, HTTPError) assert isinstance(exc, HTTPServerError) assert type(exc) == HTTPInternalServerError assert str(exc) == "500 Server Error: Holy moly!: {'msg': 'Kaboom'}"
def raise_on_expected(http_response): """Raise an HTTPError if the response is non-2XX and matches a response in the swagger spec. :param http_response: :class:`bravado_core.response.IncomingResponse` :raises: HTTPError """ if not 200 <= http_response.status_code < 300: raise make_http_exception(response=http_response, swagger_result=http_response.swagger_result)
def raise_on_expected(http_response): """Raise an HTTPError if the response is non-2XX and matches a response in the swagger spec. :param http_response: :class:`bravado_core.response.IncomingResponse` :raises: HTTPError """ if not 200 <= http_response.status_code < 300: raise make_http_exception( response=http_response, swagger_result=http_response.swagger_result)
def unmarshal_response( incoming_response, # type: IncomingResponse operation, # type: Operation response_callbacks=None, # type: typing.Optional[typing.List[typing.Callable[[typing.Any, typing.Any], None]]] ): # type: (...) -> None """So the http_client is finished with its part of processing the response. This hands the response over to bravado_core for validation and unmarshalling and then runs any response callbacks. On success, the swagger_result is available as ``incoming_response.swagger_result``. :type incoming_response: :class:`bravado_core.response.IncomingResponse` :type operation: :class:`bravado_core.operation.Operation` :type response_callbacks: list of callable. See bravado_core.client.REQUEST_OPTIONS_DEFAULTS. :raises: HTTPError - On 5XX status code, the HTTPError has minimal information. - On non-2XX status code with no matching response, the HTTPError contains a detailed error message. - On non-2XX status code with a matching response, the HTTPError contains the return value. """ response_callbacks = response_callbacks or [] try: raise_on_unexpected(incoming_response) incoming_response.swagger_result = unmarshal_response_inner( response=incoming_response, op=operation, ) except MatchingResponseNotFound as e: exception = make_http_exception( response=incoming_response, message=str(e) ) six.reraise( type(exception), exception, sys.exc_info()[2]) finally: # Always run the callbacks regardless of success/failure for response_callback in response_callbacks: response_callback(incoming_response, operation) raise_on_expected(incoming_response)
def test_make_http_exception_type(status_code, expected_type): requests_response = Response() requests_response.status_code = status_code requests_response.reason = "Womp Error" exc = make_http_exception(RequestsResponseAdapter(requests_response), ) assert type(exc) == expected_type
def response(self, timeout=None, fallback_result=SENTINEL, exceptions_to_catch=FALLBACK_EXCEPTIONS): """Blocking call to wait for the HTTP response. :param timeout: Number of seconds to wait for a response. Defaults to None which means wait indefinitely. :type timeout: float :param fallback_result: either the swagger result or a callable that accepts an exception as argument and returns the swagger result to use in case of errors :type fallback_result: Optional[Union[Any, Callable[[Exception], Any]]] :param exceptions_to_catch: Exception classes to catch and call `fallback_result` with. Has no effect if `fallback_result` is not provided. By default, `fallback_result` will be called for read timeout and server errors (HTTP 5XX). :type exceptions_to_catch: List/Tuple of Exception classes. :return: A BravadoResponse instance containing the swagger result and response metadata. """ incoming_response = None exc_info = None request_end_time = None if self.request_config.force_fallback_result: exceptions_to_catch = tuple(chain(exceptions_to_catch, (ForcedFallbackResultError,))) try: incoming_response = self._get_incoming_response(timeout) request_end_time = monotonic.monotonic() swagger_result = self._get_swagger_result(incoming_response) if self.operation is None and incoming_response.status_code >= 300: raise make_http_exception(response=incoming_response) # Trigger fallback_result if the option is set if fallback_result is not SENTINEL and self.request_config.force_fallback_result: if self.operation.swagger_spec.config['bravado'].disable_fallback_results: log.warning( 'force_fallback_result set in request options and disable_fallback_results ' 'set in client config; not using fallback result.' ) else: # raise an exception to trigger fallback result handling raise ForcedFallbackResultError() except exceptions_to_catch as e: if request_end_time is None: request_end_time = monotonic.monotonic() # the Python 2 documentation states that we shouldn't assign the traceback to a local variable, # as that would cause a circular reference. We'll store a string representation of the traceback # instead. exc_info = list(sys.exc_info()[:2]) exc_info.append(traceback.format_exc()) if ( fallback_result is not SENTINEL and self.operation and not self.operation.swagger_spec.config['bravado'].disable_fallback_results ): swagger_result = fallback_result(e) if callable(fallback_result) else fallback_result else: six.reraise(*sys.exc_info()) metadata_class = self.operation.swagger_spec.config['bravado'].response_metadata_class response_metadata = metadata_class( incoming_response=incoming_response, swagger_result=swagger_result, start_time=self._start_time, request_end_time=request_end_time, handled_exception_info=exc_info, request_config=self.request_config, ) return BravadoResponse( result=swagger_result, metadata=response_metadata, )
def response( self, timeout=None, # type: typing.Optional[float] fallback_result=SENTINEL, # type: typing.Union[_SENTINEL, T, typing.Callable[[BaseException], T]] # noqa exceptions_to_catch=FALLBACK_EXCEPTIONS, # type: typing.Tuple[typing.Type[BaseException], ...] ): # type: (...) -> BravadoResponse[T] """Blocking call to wait for the HTTP response. :param timeout: Number of seconds to wait for a response. Defaults to None which means wait indefinitely. :type timeout: float :param fallback_result: either the swagger result or a callable that accepts an exception as argument and returns the swagger result to use in case of errors :param exceptions_to_catch: Exception classes to catch and call `fallback_result` with. Has no effect if `fallback_result` is not provided. By default, `fallback_result` will be called for read timeout and server errors (HTTP 5XX). :return: A BravadoResponse instance containing the swagger result and response metadata. """ incoming_response = None exc_info = None # type: typing.Optional[typing.List[typing.Union[typing.Type[BaseException], BaseException, typing.Text]]] # noqa: E501 request_end_time = None if self.request_config.force_fallback_result: exceptions_to_catch = tuple( chain(exceptions_to_catch, (ForcedFallbackResultError, ))) try: incoming_response = self._get_incoming_response(timeout) request_end_time = monotonic.monotonic() swagger_result = self._get_swagger_result(incoming_response) if self.operation is None and incoming_response.status_code >= 300: raise make_http_exception(response=incoming_response) # Trigger fallback_result if the option is set if fallback_result is not SENTINEL and self.request_config.force_fallback_result: if self._bravado_config.disable_fallback_results: log.warning( 'force_fallback_result set in request options and disable_fallback_results ' 'set in client config; not using fallback result.') else: # raise an exception to trigger fallback result handling raise ForcedFallbackResultError() except exceptions_to_catch as e: if request_end_time is None: request_end_time = monotonic.monotonic() exc_info = [] # the return values of exc_info are annotated as Optional, but we know they are set in this case. # additionally, we can't use a cast() since that caused a runtime exception on some older versions # of Python 3.5. exc_info.extend(sys.exc_info()[:2]) # type: ignore # the Python 2 documentation states that we shouldn't assign the traceback to a local variable, # as that would cause a circular reference. We'll store a string representation of the traceback # instead. exc_info.append(traceback.format_exc()) if (fallback_result is not SENTINEL and self.operation and not self.operation.swagger_spec.config['bravado']. disable_fallback_results): if callable(fallback_result): swagger_result = fallback_result(e) else: swagger_result = typing.cast(T, fallback_result) else: six.reraise(*sys.exc_info()) metadata_class = self._bravado_config.response_metadata_class response_metadata = metadata_class( incoming_response=incoming_response, swagger_result=swagger_result, start_time=self._start_time, request_end_time=request_end_time, handled_exception_info=exc_info, request_config=self.request_config, ) return BravadoResponse( result=swagger_result, metadata=response_metadata, )
def response( self, timeout=None, # type: typing.Optional[float] fallback_result=SENTINEL, # type: typing.Union[_SENTINEL, T, typing.Callable[[BaseException], T]] # noqa exceptions_to_catch=FALLBACK_EXCEPTIONS, # type: typing.Tuple[typing.Type[BaseException], ...] ): # type: (...) -> BravadoResponse[T] """Blocking call to wait for the HTTP response. :param timeout: Number of seconds to wait for a response. Defaults to None which means wait indefinitely. :type timeout: float :param fallback_result: either the swagger result or a callable that accepts an exception as argument and returns the swagger result to use in case of errors :param exceptions_to_catch: Exception classes to catch and call `fallback_result` with. Has no effect if `fallback_result` is not provided. By default, `fallback_result` will be called for read timeout and server errors (HTTP 5XX). :return: A BravadoResponse instance containing the swagger result and response metadata. """ incoming_response = None exc_info = None # type: typing.Optional[typing.List[typing.Union[typing.Type[BaseException], BaseException, typing.Text]]] # noqa: E501 request_end_time = None if self.request_config.force_fallback_result: exceptions_to_catch = tuple(chain(exceptions_to_catch, (ForcedFallbackResultError,))) try: incoming_response = self._get_incoming_response(timeout) request_end_time = monotonic.monotonic() swagger_result = self._get_swagger_result(incoming_response) if self.operation is None and incoming_response.status_code >= 300: raise make_http_exception(response=incoming_response) # Trigger fallback_result if the option is set if fallback_result is not SENTINEL and self.request_config.force_fallback_result: if self._bravado_config.disable_fallback_results: log.warning( 'force_fallback_result set in request options and disable_fallback_results ' 'set in client config; not using fallback result.' ) else: # raise an exception to trigger fallback result handling raise ForcedFallbackResultError() except exceptions_to_catch as e: if request_end_time is None: request_end_time = monotonic.monotonic() exc_info = [] # the return values of exc_info are annotated as Optional, but we know they are set in this case. # additionally, we can't use a cast() since that caused a runtime exception on some older versions # of Python 3.5. exc_info.extend(sys.exc_info()[:2]) # type: ignore # the Python 2 documentation states that we shouldn't assign the traceback to a local variable, # as that would cause a circular reference. We'll store a string representation of the traceback # instead. exc_info.append(traceback.format_exc()) if ( fallback_result is not SENTINEL and self.operation and not self.operation.swagger_spec.config['bravado'].disable_fallback_results ): if callable(fallback_result): swagger_result = fallback_result(e) else: swagger_result = typing.cast(T, fallback_result) else: six.reraise(*sys.exc_info()) metadata_class = self._bravado_config.response_metadata_class response_metadata = metadata_class( incoming_response=incoming_response, swagger_result=swagger_result, start_time=self._start_time, request_end_time=request_end_time, handled_exception_info=exc_info, request_config=self.request_config, ) return BravadoResponse( result=swagger_result, metadata=response_metadata, )