def from_exc_info(cls, exc_info=None,
                      retain_exc_info=True,
                      cause=None, find_cause=True):
        """Creates a failure object from a ``sys.exc_info()`` tuple."""
        if exc_info is None:
            exc_info = sys.exc_info()
            if not any(exc_info):
                raise NoActiveException("No exception currently"
                                        " being handled")
        # This should always be the (type, value, traceback) tuple,
        # either from a prior sys.exc_info() call or from some other
        # creation...
        if len(exc_info) != 3:
            raise ValueError("Provided 'exc_info' must contain three"
                             " elements")
        exc_type, exc_val, exc_tb = exc_info
        try:
            if exc_type is None or exc_val is None:
                raise ValueError("Invalid exception tuple (exception"
                                 " type and exception value must"
                                 " be provided)")
            exc_args = tuple(getattr(exc_val, 'args', []))
            exc_kwargs = dict(getattr(exc_val, 'kwargs', {}))
            exc_type_names = utils.extract_roots(exc_type)
            if not exc_type_names:
                exc_type_name = reflection.get_class_name(
                    exc_val, truncate_builtins=False)
                # This should only be possible if the exception provided
                # was not really an exception...
                raise TypeError("Invalid exception type '%s' (not an"
                                " exception)" % (exc_type_name))
            exception_str = utils.exception_message(exc_val)
            if hasattr(exc_val, '__traceback_str__'):
                traceback_str = exc_val.__traceback_str__
            else:
                if exc_tb is not None:
                    traceback_str = '\n'.join(
                        traceback.format_exception(*exc_info))
                else:
                    traceback_str = ''
            if not retain_exc_info:
                exc_info = None
            if find_cause and cause is None:
                cause = cls._extract_cause(exc_val)
            return cls(exc_info=exc_info, exc_args=exc_args,
                       exc_kwargs=exc_kwargs, exception_str=exception_str,
                       exc_type_names=exc_type_names, cause=cause,
                       traceback_str=traceback_str,
                       generated_on=sys.version_info[0:2])
        finally:
            del exc_type, exc_val, exc_tb
Creates a failure object from a ``sys.exc_info()`` tuple.