src/polydatum/context.py
def _exit(self, obj, type, value, traceback):
        """
        Teardown a Resource or Middleware.
        """
        if type is None:
            # No in-context exception occurred
            try:
                obj.next()
            except StopIteration:
                # Resource closed as expected
                return
            else:
                raise RuntimeError('{} yielded more than once.'.format(obj))
        else:
            # In-context exception occurred
            try:
                obj.throw(type, value, traceback)
                raise RuntimeError('{} did not close after throw()'.format(obj))
            except StopIteration as exc:
                # Suppress the exception *unless* it's the same exception that
                # was passed to throw().  This prevents a StopIteration
                # raised inside the "with" statement from being suppressed
                return exc is not value
            except:
                # only re-raise if it's *not* the exception that was
                # passed to throw(), because __exit__() must not raise
                # an exception unless __exit__() itself failed.  But
                # resource.throw() will raise the exception to signal propagation,
                # so this fixes the impedance mismatch between the throw() protocol
                # and the __exit__() protocol.
                #
                # Middleware or Resources that throw exceptions before yielding
                # will just rethrow the same exception here which is expected. They
                # won't have a chance to do anything about the exception though which
                # seems OK since they never got to the point of being ready anyway.
                if sys.exc_info()[1] is not value:
                    raise
def _exit(self, obj, type, value, traceback):
        """
        Teardown a Resource or Middleware.
        """
        if type is None:
            # No in-context exception occurred
            try:
                obj.next()
            except StopIteration:
                # Resource closed as expected
                return
            else:
                raise RuntimeError('{} yielded more than once.'.format(obj))
        else:
            # In-context exception occurred
            try:
                obj.throw(type, value, traceback)
                raise RuntimeError('{} did not close after throw()'.format(obj))
            except StopIteration as exc:
                # Suppress the exception *unless* it's the same exception that
                # was passed to throw().  This prevents a StopIteration
                # raised inside the "with" statement from being suppressed
                return exc is not value
            except:
                # only re-raise if it's *not* the exception that was
                # passed to throw(), because __exit__() must not raise
                # an exception unless __exit__() itself failed.  But
                # resource.throw() will raise the exception to signal propagation,
                # so this fixes the impedance mismatch between the throw() protocol
                # and the __exit__() protocol.
                #
                # Middleware or Resources that throw exceptions before yielding
                # will just rethrow the same exception here which is expected. They
                # won't have a chance to do anything about the exception though which
                # seems OK since they never got to the point of being ready anyway.
                if sys.exc_info()[1] is not value:
                    raise
Teardown a Resource or Middleware.