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, )