Exemple #1
0
    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)
Exemple #2
0
    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)
Exemple #3
0
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)
Exemple #4
0
    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)
Exemple #5
0
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)
Exemple #6
0
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)
Exemple #7
0
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
Exemple #8
0
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'}"
Exemple #9
0
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)
Exemple #10
0
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)
Exemple #11
0
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)
Exemple #12
0
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
Exemple #13
0
    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,
        )
Exemple #14
0
    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,
        )
Exemple #15
0
    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,
        )