Exemplo n.º 1
0
def generic_result_renderer(res):
    if res.get('status', None) != 'notneeded':
        path = res.get('path', None)
        if path and res.get('refds'):
            try:
                path = relpath(path, res['refds'])
            except ValueError:
                # can happen, e.g., on windows with paths from different
                # drives. just go with the original path in this case
                pass
        ui.message('{action}({status}):{path}{type}{msg}{err}'.format(
            action=ac.color_word(res.get('action', '<action-unspecified>'),
                                 ac.BOLD),
            status=ac.color_status(res.get('status', '<status-unspecified>')),
            path=' {}'.format(path) if path else '',
            type=' ({})'.format(ac.color_word(res['type'], ac.MAGENTA))
            if 'type' in res else '',
            msg=' [{}]'.format(res['message'][0] %
                               res['message'][1:] if isinstance(
                                   res['message'], tuple) else res['message'])
            if res.get('message', None) else '',
            err=ac.color_word(
                ' [{}]'.format(res['error_message'][0] %
                               res['error_message'][1:] if isinstance(
                                   res['error_message'], tuple
                               ) else res['error_message']), ac.RED)
            if res.get('error_message', None)
            and res.get('status', None) != 'ok' else ''))
Exemplo n.º 2
0
def default_result_renderer(res):
    if res.get('status', None) != 'notneeded':
        ui.message('{action}({status}): {path}{type}{msg}'.format(
            action=ac.color_word(res['action'], ac.BOLD),
            status=ac.color_status(res['status']),
            path=relpath(res['path'], res['refds'])
            if res.get('refds', None) else res['path'],
            type=' ({})'.format(ac.color_word(res['type'], ac.MAGENTA))
            if 'type' in res else '',
            msg=' [{}]'.format(res['message'][0] %
                               res['message'][1:] if isinstance(
                                   res['message'], tuple) else res['message'])
            if 'message' in res else ''))
Exemplo n.º 3
0
def test_color_status():
    # status -> (plain, colored)
    statuses = {
        'ok': ('ok', '\033[1;32mok\033[0m'),
        'notneeded': ('notneeded', '\033[1;32mnotneeded\033[0m'),
        'impossible': ('impossible', '\033[1;33mimpossible\033[0m'),
        'error': ('error', '\033[1;31merror\033[0m'),
        'invalid': ('invalid', 'invalid'),
        }

    for enabled in (True, False):
        with patch('datalad.support.ansi_colors.color_enabled', lambda: enabled):
            for status, retopts in statuses.items():
                assert_equal(colors.color_status(status), retopts[enabled])
Exemplo n.º 4
0
def default_result_renderer(res):
    if res.get('status', None) != 'notneeded':
        ui.message('{action}({status}): {path}{type}{msg}'.format(
                action=ac.color_word(res['action'], ac.BOLD),
                status=ac.color_status(res['status']),
                path=relpath(res['path'],
                             res['refds']) if res.get('refds', None) else res[
                    'path'],
                type=' ({})'.format(
                        ac.color_word(res['type'], ac.MAGENTA)
                ) if 'type' in res else '',
                msg=' [{}]'.format(
                        res['message'][0] % res['message'][1:]
                        if isinstance(res['message'], tuple) else res[
                            'message'])
                if 'message' in res else ''))
Exemplo n.º 5
0
def _process_results(
        results, cmd_class,
        action_summary, on_failure, incomplete_results,
        result_renderer, result_xfm, result_filter, **kwargs):
    # private helper pf @eval_results
    # loop over results generated from some source and handle each
    # of them according to the requested behavior (logging, rendering, ...)
    for res in results:
        if not res or 'action' not in res:
            # XXX Yarik has to no clue on how to track the origin of the
            # record to figure out WTF, so he just skips it
            continue

        if PY2:
            for k, v in res.items():
                if isinstance(v, unicode):
                    res[k] = v.encode('utf-8')

        actsum = action_summary.get(res['action'], {})
        if res['status']:
            actsum[res['status']] = actsum.get(res['status'], 0) + 1
            action_summary[res['action']] = actsum
        ## log message, if a logger was given
        # remove logger instance from results, as it is no longer useful
        # after logging was done, it isn't serializable, and generally
        # pollutes the output
        res_lgr = res.pop('logger', None)
        if isinstance(res_lgr, logging.Logger):
            # didn't get a particular log function, go with default
            res_lgr = getattr(res_lgr, default_logchannels[res['status']])
        if res_lgr and 'message' in res:
            msg = res['message']
            msgargs = None
            if isinstance(msg, tuple):
                msgargs = msg[1:]
                msg = msg[0]
            if 'path' in res:
                msg = '{} [{}({})]'.format(
                    msg, res['action'], res['path'])
            if msgargs:
                # support string expansion of logging to avoid runtime cost
                res_lgr(msg, *msgargs)
            else:
                res_lgr(msg)
        ## error handling
        # looks for error status, and report at the end via
        # an exception
        if on_failure in ('continue', 'stop') \
                and res['status'] in ('impossible', 'error'):
            incomplete_results.append(res)
            if on_failure == 'stop':
                # first fail -> that's it
                # raise will happen after the loop
                break
        if result_filter:
            try:
                if not result_filter(res):
                    raise ValueError('excluded by filter')
            except ValueError as e:
                lgr.debug('not reporting result (%s)', exc_str(e))
                continue
        ## output rendering
        # TODO RF this in a simple callable that gets passed into this function
        if result_renderer is None or result_renderer == 'disabled':
            pass
        elif result_renderer == 'default':
            # TODO have a helper that can expand a result message
            ui.message('{action}({status}): {path}{type}{msg}'.format(
                action=ac.color_word(res['action'], ac.BOLD),
                status=ac.color_status(res['status']),
                path=relpath(res['path'],
                             res['refds']) if res.get('refds', None) else res['path'],
                type=' ({})'.format(
                    ac.color_word(res['type'], ac.MAGENTA)
                    ) if 'type' in res else '',
                msg=' [{}]'.format(
                    res['message'][0] % res['message'][1:]
                    if isinstance(res['message'], tuple) else res['message'])
                if 'message' in res else ''))
        elif result_renderer in ('json', 'json_pp'):
            ui.message(json.dumps(
                {k: v for k, v in res.items()
                 if k not in ('message', 'logger')},
                sort_keys=True,
                indent=2 if result_renderer.endswith('_pp') else None))
        elif result_renderer == 'tailored':
            if hasattr(cmd_class, 'custom_result_renderer'):
                cmd_class.custom_result_renderer(res, **kwargs)
        elif hasattr(result_renderer, '__call__'):
            try:
                result_renderer(res, **kwargs)
            except Exception as e:
                lgr.warn('Result rendering failed for: %s [%s]',
                         res, exc_str(e))
        else:
            raise ValueError('unknown result renderer "{}"'.format(result_renderer))

        if PY2:
            for k, v in res.items():
                if isinstance(v, str):
                    res[k] = v.decode('utf-8')

        if result_xfm:
            res = result_xfm(res)
            if res is None:
                continue
        yield res