[errors] Move error handling in transformations to use mondrian.

This commit is contained in:
Romain Dorgueil
2017-11-02 00:08:09 +01:00
parent 58923f4a84
commit fb86bc9507
15 changed files with 45 additions and 31 deletions

View File

@ -1,4 +1,4 @@
# Generated by Medikit 0.4a9 on 2017-11-01. # Generated by Medikit 0.4a10 on 2017-11-01.
# All changes will be overriden. # All changes will be overriden.
PACKAGE ?= bonobo PACKAGE ?= bonobo

View File

@ -42,7 +42,7 @@ python.setup(
python.add_requirements( python.add_requirements(
'fs >=2.0,<2.1', 'fs >=2.0,<2.1',
'jinja2 >=2.9,<2.10', 'jinja2 >=2.9,<2.10',
'mondrian >=0.2,<0.3', 'mondrian >=0.3,<0.4',
'packaging >=16,<17', 'packaging >=16,<17',
'psutil >=5.4,<6.0', 'psutil >=5.4,<6.0',
'requests >=2.0,<3.0', 'requests >=2.0,<3.0',

View File

@ -9,6 +9,7 @@
import sys import sys
assert (sys.version_info >= (3, 5)), 'Python 3.5+ is required to use Bonobo.' assert (sys.version_info >= (3, 5)), 'Python 3.5+ is required to use Bonobo.'
from bonobo._api import * from bonobo._api import *
from bonobo._api import __all__ from bonobo._api import __all__
from bonobo._version import __version__ from bonobo._version import __version__

View File

@ -40,7 +40,6 @@ def run(graph, *, plugins=None, services=None, strategy=None):
:param dict services: The implementations of services this graph will use. :param dict services: The implementations of services this graph will use.
:return bonobo.execution.graph.GraphExecutionContext: :return bonobo.execution.graph.GraphExecutionContext:
""" """
strategy = create_strategy(strategy)
plugins = plugins or [] plugins = plugins or []
@ -49,6 +48,10 @@ def run(graph, *, plugins=None, services=None, strategy=None):
if not settings.QUIET.get(): # pragma: no cover if not settings.QUIET.get(): # pragma: no cover
if _is_interactive_console(): if _is_interactive_console():
import mondrian
mondrian.setup()
mondrian.setupExceptHook()
from bonobo.ext.console import ConsoleOutputPlugin from bonobo.ext.console import ConsoleOutputPlugin
if ConsoleOutputPlugin not in plugins: if ConsoleOutputPlugin not in plugins:
plugins.append(ConsoleOutputPlugin) plugins.append(ConsoleOutputPlugin)
@ -67,7 +70,7 @@ def run(graph, *, plugins=None, services=None, strategy=None):
if JupyterOutputPlugin not in plugins: if JupyterOutputPlugin not in plugins:
plugins.append(JupyterOutputPlugin) plugins.append(JupyterOutputPlugin)
return strategy.execute(graph, plugins=plugins, services=services) return create_strategy(strategy).execute(graph, plugins=plugins, services=services)
def _inspect_as_graph(graph): def _inspect_as_graph(graph):

View File

@ -1,11 +1,9 @@
import argparse import argparse
import traceback
import logging import logging
import mondrian
import mondrian
from bonobo import settings from bonobo import settings
from bonobo.commands.base import BaseCommand, BaseGraphCommand from bonobo.commands.base import BaseCommand, BaseGraphCommand
from bonobo.util.errors import print_error
def entrypoint(args=None): def entrypoint(args=None):
@ -16,7 +14,10 @@ def entrypoint(args=None):
""" """
logger = mondrian.getLogger() mondrian.setup()
mondrian.setupExceptHook()
logger = logging.getLogger()
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('--debug', '-D', action='store_true') parser.add_argument('--debug', '-D', action='store_true')
@ -56,9 +57,6 @@ def entrypoint(args=None):
# Get command handler, execute, rince. # Get command handler, execute, rince.
command = commands[parsed_args.pop('command')] command = commands[parsed_args.pop('command')]
command(**parsed_args)
try: return 0
command(**parsed_args)
except Exception as exc:
print_error(exc, traceback.format_exc())
return 255

View File

@ -12,7 +12,6 @@ EXAMPLES_BASE_URL = 'https://raw.githubusercontent.com/python-bonobo/bonobo/mast
class DownloadCommand(BaseCommand): class DownloadCommand(BaseCommand):
def handle(self, *, path, **options): def handle(self, *, path, **options):
path = path.lstrip('/')
if not path.startswith('examples'): if not path.startswith('examples'):
raise ValueError('Download command currently supports examples only') raise ValueError('Download command currently supports examples only')
examples_path = re.sub('^examples/', '', path) examples_path = re.sub('^examples/', '', path)

View File

@ -13,7 +13,7 @@ class InitCommand(BaseCommand):
parser.add_argument('filename') parser.add_argument('filename')
parser.add_argument('--force', '-f', default=False, action='store_true') parser.add_argument('--force', '-f', default=False, action='store_true')
target_group = parser.add_mutually_exclusive_group(required=True) target_group = parser.add_mutually_exclusive_group(required=False)
target_group.add_argument('--template', '-t', choices=self.TEMPLATES, default='default') target_group.add_argument('--template', '-t', choices=self.TEMPLATES, default='default')
target_group.add_argument('--package', '-p', action='store_true', default=False) target_group.add_argument('--package', '-p', action='store_true', default=False)
@ -41,11 +41,13 @@ class InitCommand(BaseCommand):
import medikit.commands import medikit.commands
except ImportError as exc: except ImportError as exc:
raise ImportError( raise ImportError(
'To initialize a package, you need to install medikit (pip install --upgrade medikit).') from exc 'To initialize a package, you need to install medikit (pip install --upgrade medikit).'
) from exc
package_name = os.path.basename(filename) package_name = os.path.basename(filename)
medikit.commands.handle_init(os.path.join(os.getcwd(), filename, 'Projectfile'), name=package_name, medikit.commands.handle_init(
requirements=['bonobo']) os.path.join(os.getcwd(), filename, 'Projectfile'), name=package_name, requirements=['bonobo']
)
self.logger.info('Generated "{}" package with medikit.'.format(package_name)) self.logger.info('Generated "{}" package with medikit.'.format(package_name))
self.create_file_from_template(template='default', filename=os.path.join(filename, package_name, '__main__.py')) self.create_file_from_template(template='default', filename=os.path.join(filename, package_name, '__main__.py'))

View File

@ -1 +1,3 @@
from bonobo.execution.graph import GraphExecutionContext, NodeExecutionContext, PluginExecutionContext import logging
logger = logging.getLogger(__name__)

View File

@ -1,12 +1,17 @@
import traceback import logging
from contextlib import contextmanager from contextlib import contextmanager
from logging import WARNING, ERROR
from time import sleep from time import sleep
import sys
import mondrian
from bonobo.config import create_container from bonobo.config import create_container
from bonobo.config.processors import ContextCurrifier from bonobo.config.processors import ContextCurrifier
from bonobo.util import isconfigurabletype from bonobo.util import isconfigurabletype
from bonobo.util.errors import print_error
from bonobo.util.objects import Wrapper, get_name from bonobo.util.objects import Wrapper, get_name
from bonobo.execution import logger
@contextmanager @contextmanager
@ -14,7 +19,7 @@ def recoverable(error_handler):
try: try:
yield yield
except Exception as exc: # pylint: disable=broad-except except Exception as exc: # pylint: disable=broad-except
error_handler(exc, traceback.format_exc()) error_handler(*sys.exc_info(), level=ERROR)
@contextmanager @contextmanager
@ -22,7 +27,7 @@ def unrecoverable(error_handler):
try: try:
yield yield
except Exception as exc: # pylint: disable=broad-except except Exception as exc: # pylint: disable=broad-except
error_handler(exc, traceback.format_exc()) error_handler(*sys.exc_info(), level=ERROR)
raise # raise unrecoverableerror from x ? raise # raise unrecoverableerror from x ?
@ -101,8 +106,10 @@ class LoopingExecutionContext(Wrapper):
finally: finally:
self._stopped = True self._stopped = True
def handle_error(self, exc, trace): def handle_error(self, exctype, exc, tb):
return print_error(exc, trace, context=self.wrapped) mondrian.excepthook(
exctype, exc, tb, level=WARNING, context='{} in {}'.format(exctype.__name__, get_name(self)), logger=logger
)
def _get_initial_context(self): def _get_initial_context(self):
if self.parent: if self.parent:

View File

@ -3,6 +3,8 @@ from queue import Empty
from time import sleep from time import sleep
from types import GeneratorType from types import GeneratorType
import sys
from bonobo.constants import NOT_MODIFIED, BEGIN, END from bonobo.constants import NOT_MODIFIED, BEGIN, END
from bonobo.errors import InactiveReadableError, UnrecoverableError from bonobo.errors import InactiveReadableError, UnrecoverableError
from bonobo.execution.base import LoopingExecutionContext from bonobo.execution.base import LoopingExecutionContext
@ -101,11 +103,11 @@ class NodeExecutionContext(WithStatistics, LoopingExecutionContext):
sleep(self.PERIOD) sleep(self.PERIOD)
continue continue
except UnrecoverableError as exc: except UnrecoverableError as exc:
self.handle_error(exc, traceback.format_exc()) self.handle_error(*sys.exc_info())
self.input.shutdown() self.input.shutdown()
break break
except Exception as exc: # pylint: disable=broad-except except Exception as exc: # pylint: disable=broad-except
self.handle_error(exc, traceback.format_exc()) self.handle_error(*sys.exc_info())
def step(self): def step(self):
# Pull data from the first available input channel. # Pull data from the first available input channel.

View File

@ -5,7 +5,6 @@ from django.core.management.base import BaseCommand, OutputWrapper
import bonobo import bonobo
import bonobo.util import bonobo.util
from bonobo.commands import get_default_services
from bonobo.ext.console import ConsoleOutputPlugin from bonobo.ext.console import ConsoleOutputPlugin
from bonobo.util.term import CLEAR_EOL from bonobo.util.term import CLEAR_EOL

View File

@ -1,4 +1,5 @@
import logging import logging
import os import os
from bonobo.errors import ValidationError from bonobo.errors import ValidationError

View File

@ -7,7 +7,7 @@ fs==2.0.12
idna==2.6 idna==2.6
jinja2==2.9.6 jinja2==2.9.6
markupsafe==1.0 markupsafe==1.0
mondrian==0.2.0 mondrian==0.3.0
packaging==16.8 packaging==16.8
pbr==3.1.1 pbr==3.1.1
psutil==5.4.0 psutil==5.4.0

View File

@ -53,7 +53,7 @@ setup(
packages=find_packages(exclude=['ez_setup', 'example', 'test']), packages=find_packages(exclude=['ez_setup', 'example', 'test']),
include_package_data=True, include_package_data=True,
install_requires=[ install_requires=[
'colorama (>= 0.3)', 'fs (>= 2.0, < 2.1)', 'jinja2 (>= 2.9, < 2.10)', 'mondrian (>= 0.2, < 0.3)', 'colorama (>= 0.3)', 'fs (>= 2.0, < 2.1)', 'jinja2 (>= 2.9, < 2.10)', 'mondrian (>= 0.3, < 0.4)',
'packaging (>= 16, < 17)', 'psutil (>= 5.4, < 6.0)', 'requests (>= 2.0, < 3.0)', 'stevedore (>= 1.27, < 1.28)' 'packaging (>= 16, < 17)', 'psutil (>= 5.4, < 6.0)', 'requests (>= 2.0, < 3.0)', 'stevedore (>= 1.27, < 1.28)'
], ],
extras_require={ extras_require={

View File

@ -164,7 +164,7 @@ def test_download_works_for_examples(runner):
@all_runners @all_runners
def test_download_fails_non_example(runner): def test_download_fails_non_example(runner):
with pytest.raises(ValueError): with pytest.raises(ValueError):
runner('download', '/something/entirely/different.txt') runner('download', 'something/entirely/different.txt')
@pytest.fixture @pytest.fixture