Beispiel #1
0
    def custom_result_renderer(res, **kwargs):
        from datalad.interface.utils import generic_result_renderer
        from datalad.ui import ui

        if res['status'] != 'ok' or 'procedure' not in res.get('action', ''):
            # it's not our business
            generic_result_renderer(res)
            return

        if kwargs.get('discover', None):
            ui.message('{name} ({path}){msg}'.format(
                # bold-faced name, if active
                name=ac.color_word(res['procedure_name'], ac.BOLD)
                if res['state'] == 'executable' else res['procedure_name'],
                path=res['path'],
                msg=' [{}]'.format(
                    res['message'][0] %
                    res['message'][1:] if isinstance(res['message'], tuple)
                    else res['message']) if 'message' in res else ''))

        elif kwargs.get('help_proc', None):
            ui.message('{name} ({path}){help}'.format(
                name=ac.color_word(res['procedure_name'], ac.BOLD),
                path=op.relpath(res['path'], res['refds']) if res.get(
                    'refds', None) else res['path'],
                help='{nl}{msg}'.format(
                    nl=os.linesep,
                    msg=res['message'][0] %
                    res['message'][1:] if isinstance(res['message'], tuple)
                    else res['message']) if 'message' in res else ''))

        else:
            generic_result_renderer(res)
Beispiel #2
0
 def custom_result_renderer(res, **kwargs):  # pragma: more cover
     if (res['status'] == 'ok' and res['action'] in ('status', 'diff')
             and res.get('state') == 'clean'):
         # this renderer will be silent for clean status|diff results
         return
     if res['status'] != 'ok' or res['action'] not in ('status', 'diff'):
         # whatever this renderer cannot account for, send to generic
         generic_result_renderer(res)
         return
     from datalad.ui import ui
     # when to render relative paths:
     #  1) if a dataset arg was given
     #  2) if CWD is the refds
     refds = res.get('refds', None)
     refds = refds if kwargs.get('dataset', None) is not None \
         or refds == os.getcwd() else None
     path = res['path'] if refds is None \
         else str(ut.Path(res['path']).relative_to(refds))
     type_ = res.get('type', res.get('type_src', ''))
     max_len = len('untracked')
     state = res.get('state', 'unknown')
     ui.message(u'{fill}{state}: {path}{type_}'.format(
         fill=' ' * max(0, max_len - len(state)),
         state=ac.color_word(
             state, STATE_COLOR_MAP.get(res.get('state', 'unknown'))),
         path=path,
         type_=' ({})'.format(
             ac.color_word(type_, ac.MAGENTA) if type_ else '')))
Beispiel #3
0
 def custom_result_renderer(res, **kwargs):
     dry_run = kwargs.get("dry_run")
     if dry_run and "dry_run_info" in res:
         if dry_run == "basic":
             _display_basic(res)
         elif dry_run == "command":
             ui.message(res["dry_run_info"]["cmd_expanded"])
         else:
             raise ValueError(f"Unknown dry-run mode: {dry_run!r}")
     else:
         if kwargs.get("on_failure") == "stop" and \
            res.get("action") == "run" and res.get("status") == "error":
             msg_path = res.get("msg_path")
             if msg_path:
                 ds_path = res["path"]
                 if datalad.get_apimode() == 'python':
                     help = f"\"Dataset('{ds_path}').save(path='.', " \
                            "recursive=True, message_file='%s')\""
                 else:
                     help = "'datalad save -d . -r -F %s'"
                 lgr.info(
                     "The command had a non-zero exit code. "
                     "If this is expected, you can save the changes with "
                     f"{help}",
                     # shorten to the relative path for a more concise
                     # message
                     Path(msg_path).relative_to(ds_path))
         generic_result_renderer(res)
Beispiel #4
0
    def custom_result_renderer(res, **kwargs):
        from datalad.ui import ui

        # should we attempt to remove an unknown sibling, complain like Git does
        if res['status'] == 'notneeded' and res['action'] == 'remove-sibling':
            ui.message('{warn}: No sibling "{name}" in dataset {path}'.format(
                warn=ac.color_word('Warning', ac.LOG_LEVEL_COLORS['WARNING']),
                **res))
            return
        if res['status'] != 'ok' or not res.get('action',
                                                '').endswith('-sibling'):
            generic_result_renderer(res)
            return
        path = op.relpath(res['path'], res['refds']) if res.get(
            'refds', None) else res['path']
        got_url = 'url' in res
        spec = '{}{}{}{}'.format(res.get('url', ''), ' (' if got_url else '',
                                 res.get('annex-externaltype', 'git'),
                                 ')' if got_url else '')
        ui.message('{path}: {name}({with_annex}) [{spec}]'.format(
            **dict(
                res,
                path=path,
                # TODO report '+' for special remotes
                with_annex='+' if 'annex-uuid' in res \
                    else ('-' if res.get('annex-ignore', None) else '?'),
                spec=spec)))
Beispiel #5
0
 def custom_result_renderer(res, **kwargs):
     if res['status'] != 'ok' or not res.get('action', None) == 'metadata':
         generic_result_renderer(res)
         return
     # list the path, available metadata keys, and tags
     path = op.relpath(res['path'], res['refds']) if res.get(
         'refds', None) else res['path']
     meta = res.get('metadata', {})
     ui.message('{path}{type}:{spacer}{meta}{tags}'.format(
         path=ac.color_word(path, ac.BOLD),
         type=' ({})'.format(ac.color_word(res['type'], ac.MAGENTA))
         if 'type' in res else '',
         spacer=' ' if len([m for m in meta if m != 'tag']) else '',
         meta=','.join(k for k in sorted(meta.keys())
                       if k not in ('tag', '@context', '@id'))
         if meta else ' -' if 'metadata' in res else ' aggregated',
         tags='' if 'tag' not in meta else ' [{}]'.format(','.join(
             ensure_list(meta['tag'])))))
Beispiel #6
0
    def custom_result_renderer(res, **kwargs):  # pragma: more cover
        # Don't render things like 'status' for clean-info messages -
        # seems rather meaningless.

        from os import getcwd

        import datalad.support.ansi_colors as ac
        from datalad.interface.utils import generic_result_renderer
        from datalad.utils import Path

        if res['action'] == 'clean':
            # default renderer is just fine
            return generic_result_renderer(res)
        elif res['action'] != 'clean [dry-run]':
            # Result didn't come from within `clean`.
            # Should be handled elsewhere.
            return

        assert res['action'] == 'clean [dry-run]'

        if res.get('status', None) == 'ok':
            from datalad.ui import ui

            # when to render relative paths:
            #  1) if a dataset arg was given
            #  2) if CWD is the refds

            refds = res.get('refds', None)
            refds = refds if kwargs.get('dataset', None) is not None \
                             or refds == getcwd() else None
            path = res['path'] if refds is None \
                else str(Path(res['path']).relative_to(refds))

            ui.message(u"{path}: {message}".format(
                path=ac.color_word(path, ac.BOLD),
                message=(res['message'][0] % res['message'][1:] if isinstance(
                    res['message'], tuple) else res['message']) if res.get(
                        'message', None) else ''))

        else:
            # Any other status than 'ok' is reported the default way.
            return generic_result_renderer(res)
Beispiel #7
0
def test_generic_result_renderer():
    # a bunch of bad cases of results
    testcases = [
        # an empty result will surface
        ({}, ['<action-unspecified>(<status-unspecified>)']),
        # non-standard status makes it out again
        (dict(status='funky'), ['<action-unspecified>(funky)']),
        # just an action result is enough to get some output
        (dict(action='funky'), ['funky(<status-unspecified>)']),
        # a plain path produces output, although
        (dict(path='funky'),
         ['<action-unspecified>(<status-unspecified>): funky']),
        # plain type makes it through
        (dict(type='funky'),
         ['<action-unspecified>(<status-unspecified>): (funky)']),
        # plain message makes it through
        (dict(message='funky', error_message='extra-funky'),
         ['<action-unspecified>(<status-unspecified>): [funky] [extra-funky]'
          ]),
    ]
    if on_windows:
        testcases.extend([
            # if relpath'ing is not possible, takes the path verbatim
            (dict(path='C:\\funky', refds='D:\\medina'),
             ['<action-unspecified>(<status-unspecified>): C:\\funky']),
        ])
    else:
        testcases.extend([
            (dict(path='/funky/cold/medina', refds='/funky'),
             ['<action-unspecified>(<status-unspecified>): cold/medina']),
        ])
    for result, contenttests in testcases:
        with swallow_outputs() as cmo:
            generic_result_renderer(result)
            for ctest in contenttests:
                assert_in(ctest, cmo.out)
Beispiel #8
0
 def custom_result_renderer(res, **kwargs):
     generic_result_renderer(res)