Better error display.

This commit is contained in:
Romain Dorgueil
2017-05-22 15:57:11 +02:00
parent 39e083e594
commit 329296ce6b
7 changed files with 37 additions and 15 deletions

View File

@ -2,6 +2,7 @@ import re
import types import types
from bonobo.config.options import Option from bonobo.config.options import Option
from bonobo.errors import MissingServiceImplementationError
_service_name_re = re.compile(r"^[^\d\W]\w*(:?\.[^\d\W]\w*)*$", re.UNICODE) _service_name_re = re.compile(r"^[^\d\W]\w*(:?\.[^\d\W]\w*)*$", re.UNICODE)
@ -78,7 +79,7 @@ class Container(dict):
if not name in self: if not name in self:
if default: if default:
return default return default
raise KeyError('Cannot resolve service {!r} using provided service collection.'.format(name)) raise MissingServiceImplementationError('Cannot resolve service {!r} using provided service collection.'.format(name))
value = super().get(name) value = super().get(name)
if isinstance(value, types.LambdaType): if isinstance(value, types.LambdaType):
value = value(self) value = value(self)

View File

@ -55,4 +55,7 @@ class ProhibitedOperationError(RuntimeError):
class ConfigurationError(Exception): class ConfigurationError(Exception):
pass
class MissingServiceImplementationError(KeyError):
pass pass

View File

@ -0,0 +1,5 @@
from bonobo import get_examples_path, open_fs
def get_services():
return {'fs': open_fs(get_examples_path())}

View File

@ -55,10 +55,9 @@ class LoopingExecutionContext(Wrapper):
raise RuntimeError('Cannot start a node twice ({}).'.format(get_name(self))) raise RuntimeError('Cannot start a node twice ({}).'.format(get_name(self)))
self._started = True self._started = True
self._stack = ContextCurrifier(self.wrapped, *self._get_initial_context())
with unrecoverable(self.handle_error): self._stack = ContextCurrifier(self.wrapped, *self._get_initial_context())
self._stack.setup(self) self._stack.setup(self)
for enhancer in self._enhancers: for enhancer in self._enhancers:
with unrecoverable(self.handle_error): with unrecoverable(self.handle_error):
@ -82,7 +81,7 @@ class LoopingExecutionContext(Wrapper):
return return
try: try:
with unrecoverable(self.handle_error): if self._stack:
self._stack.teardown() self._stack.teardown()
finally: finally:
self._stopped = True self._stopped = True

0
bonobo/nodes/io/xml.py Normal file
View File

View File

@ -36,7 +36,7 @@ class ExecutorStrategy(Strategy):
plugin_context.loop() plugin_context.loop()
plugin_context.stop() plugin_context.stop()
except Exception as exc: except Exception as exc:
print_error(exc, traceback.format_exc(), prefix='Error in plugin context', context=plugin_context) print_error(exc, traceback.format_exc(), context=plugin_context)
futures.append(executor.submit(_runner)) futures.append(executor.submit(_runner))
@ -46,9 +46,7 @@ class ExecutorStrategy(Strategy):
try: try:
node_context.start() node_context.start()
except Exception as exc: except Exception as exc:
print_error( print_error(exc, traceback.format_exc(), context=node_context, method='start')
exc, traceback.format_exc(), prefix='Could not start node context', context=node_context
)
node_context.input.on_end() node_context.input.on_end()
else: else:
node_context.loop() node_context.loop()
@ -56,7 +54,7 @@ class ExecutorStrategy(Strategy):
try: try:
node_context.stop() node_context.stop()
except Exception as exc: except Exception as exc:
print_error(exc, traceback.format_exc(), prefix='Could not stop node context', context=node_context) print_error(exc, traceback.format_exc(), context=node_context, method='stop')
futures.append(executor.submit(_runner)) futures.append(executor.submit(_runner))

View File

@ -1,5 +1,7 @@
import sys import sys
from textwrap import indent
from bonobo import settings
from bonobo.structs.bags import ErrorBag from bonobo.structs.bags import ErrorBag
@ -7,7 +9,14 @@ def is_error(bag):
return isinstance(bag, ErrorBag) return isinstance(bag, ErrorBag)
def print_error(exc, trace, context=None, prefix=''): def _get_error_message(exc):
if hasattr(exc, '__str__'):
message = str(exc)
return message[0].upper() + message[1:]
return '\n'.join(exc.args),
def print_error(exc, trace, context=None, method=None):
""" """
Error handler. Whatever happens in a plugin or component, if it looks like an exception, taste like an exception Error handler. Whatever happens in a plugin or component, if it looks like an exception, taste like an exception
or somehow make me think it is an exception, I'll handle it. or somehow make me think it is an exception, I'll handle it.
@ -18,14 +27,21 @@ def print_error(exc, trace, context=None, prefix=''):
""" """
from colorama import Fore, Style from colorama import Fore, Style
prefix = '{}{} | {}'.format(Fore.RED, Style.BRIGHT, Style.RESET_ALL)
print( print(
Style.BRIGHT, Style.BRIGHT,
Fore.RED, Fore.RED,
'\U0001F4A3 {}{}{}'.format( type(exc).__name__,
(prefix + ': ') if prefix else '', type(exc).__name__, ' in {!r}'.format(context) if context else '' ' (in {}{})'.format(type(context).__name__, '.{}()'.format(method) if method else '') if context else '',
), Style.RESET_ALL,
'\n',
indent(_get_error_message(exc), prefix+Style.BRIGHT),
Style.RESET_ALL, Style.RESET_ALL,
sep='', sep='',
file=sys.stderr, file=sys.stderr,
) )
print(trace) print(prefix, file=sys.stderr)
print(indent(trace, prefix, predicate=lambda line: True), file=sys.stderr)