Source code for traits.observation.exception_handling

# (C) Copyright 2005-2022 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

# This module provides the push_exception_handler and pop_exception_handler
# for the observers.

import logging
import sys


_logger = logging.getLogger("traits")


[docs]class ObserverExceptionHandler: """ State for an exception handler. Parameters ---------- handler : callable(event) or None A callable to handle an event, in the context of an exception. If None, the exceptions will be logged. reraise_exceptions : boolean Whether to reraise the exception. """ def __init__(self, handler, reraise_exceptions): self.handler = handler if handler is not None else self._log_exception self.reraise_exceptions = reraise_exceptions def _log_exception(self, event): """ A handler that logs the exception with the given event. Parameters ---------- event : object An event object emitted by the notification. """ _logger.exception( "Exception occurred in traits notification handler " "for event object: %r", event, )
[docs]class ObserverExceptionHandlerStack: """ A stack of exception handlers. Parameters ---------- handlers : list of ObserverExceptionHandler The last item is the current handler. """ def __init__(self): self.handlers = []
[docs] def push_exception_handler( self, handler=None, reraise_exceptions=False): """ Push a new exception handler into the stack. Making it the current exception handler. Parameters ---------- handler : callable(event) or None A callable to handle an event, in the context of an exception. If None, the exceptions will be logged. reraise_exceptions : boolean Whether to reraise the exception. """ self.handlers.append( ObserverExceptionHandler( handler=handler, reraise_exceptions=reraise_exceptions, ) )
[docs] def pop_exception_handler(self): """ Pop the current exception handler from the stack. Raises ------ IndexError If there are no handlers to pop. """ return self.handlers.pop()
[docs] def handle_exception(self, event): """ Handle a notification exception using the handler last pushed. Parameters ---------- event : object An event object emitted by the notification. """ _, excp, _ = sys.exc_info() try: handler_state = self.handlers[-1] except IndexError: handler_state = ObserverExceptionHandler( handler=None, reraise_exceptions=False, ) handler_state.handler(event) if handler_state.reraise_exceptions: raise excp
_exception_handler_stack = ObserverExceptionHandlerStack() push_exception_handler = _exception_handler_stack.push_exception_handler pop_exception_handler = _exception_handler_stack.pop_exception_handler handle_exception = _exception_handler_stack.handle_exception