Esempio n. 1
0
def _subcommand_graph(sin, sout, serr, argv, efx):
    """Experimental graph-viz visualization of issues..

    Use tags in your issue rows like `#after:[#123.4]` or `#part-of:[#123.4]`
    """

    prog_name = (bash_argv := list(reversed(argv))).pop()
    foz = _formals_via(_formals_for_graph(), lambda: prog_name)
    vals, es = foz.terminal_parse(serr, bash_argv)
    if vals is None:
        return es

    if vals.get('help'):
        return foz.write_help_into(serr, _subcommand_graph.__doc__)

    readme = efx.resolve_issues_file_path()
    if readme is None:
        return 4

    mon = efx.emission_monitor
    from pho._issues import issues_collection_via_ as func
    ic = func(readme, mon.listener)
    # ..

    kw = {}
    kw['targets'] = vals.get('add_target', ())
    kw['show_group_nodes'] = vals.get('show_group_nodes', False)
    kw['show_identifiers'] = vals.get('show_identifiers', False)
    from pho._issues.graph import to_graph_lines_ as func
    for line in func(ic, mon.listener, **kw):
        sout.write(line)

    return mon.exitstatus
Esempio n. 2
0
    def build_hunks_iterator():
        from text_lib.diff_and_patch import \
            next_hunk_via_line_scanner as func, scanner_via_iterator

        scn = scanner_via_iterator(output_lines_of_git_log)
        if scn.empty:
            return
        yield func(scn)
        while scn.more:
            # expect a blank line because git puts one between the last hunk
            # line and the next nerfulous derfulous line. which is fine
            assert '\n' == scn.peek
            scn.advance()
            yield func(scn)
Esempio n. 3
0
def _subcommand_use(sin, sout, serr, argv, efx):
    """Use a different readme (a shellable line. experimental)

    EXPERIMENTALLY you can try `$( pi use ./foo/bar/README.md )`
    You can get a list of available files with the `find` subcommand
    sibling to this one.
    """

    prog_name = (bash_argv := list(reversed(argv))).pop()
    foz = _formals_via(_formals_for_use(), lambda: prog_name)
    vals, es = foz.terminal_parse(serr, bash_argv)
    if vals is None:
        return es

    if vals.get('help'):
        return foz.write_help_into(serr, _subcommand_use.__doc__)

    readme = vals.pop('readme')
    do_write = vals.pop('write', False)
    assert not vals

    mon = efx.emission_monitor
    from pho._issues.dotfile_ import write_dotfile as func

    here = efx.produce_dotfile_path()

    for line in func(here, readme, do_write, mon.listener):
        sout.write(line)
        if not line or '\n' != line[-1]:
            sout.write('\n')

    return mon.returncode
Esempio n. 4
0
def _subcommand_close(sin, sout, serr, argv, efx):
    """Close an open issue..

    Actually what this probably does is update *any* issue to become a '#hole'.
    It does not actually confirm that the issue is open, as far as we know.
    """

    prog_name = (bash_argv := list(reversed(argv))).pop()
    foz = _formals_via(_formals_for_close(), lambda: prog_name)
    vals, es = foz.terminal_parse(serr, bash_argv)
    if vals is None:
        return es

    if vals.get('help'):
        return foz.write_help_into(serr, _subcommand_close.__doc__)

    eid = vals['identifier']

    is_dry = vals.get('dry_run', False)
    mon = efx.emission_monitor
    listener = mon.listener

    readme = efx.resolve_issues_file_path()
    if readme is None:
        return 4

    from pho._issues.edit import close_issue as func
    cs = func(readme, eid, listener, efx.produce_open_function())
    if cs is None:
        return mon.exitstatus

    efx.apply_patch(cs.diff_lines, is_dry, listener)  # result is t/f
    return mon.exitstatus
Esempio n. 5
0
    def line_offsets_and_lines():
        el = retr.entity_section

        from . import start_line_offset_via_vendor_element_ as func
        start_LO = func(el)
        bot = retr.body_of_text
        all_file_lines = bot.lines
        from ._blocks_via_path import line_index_via_lines_ as func
        line_index = func(all_file_lines)
        stop_LO = line_index.stop_line_offset_of_vendor_element(el)

        # Advance the end pointer to include whitespace because why not
        last_LO = len(all_file_lines)
        while stop_LO < last_LO and '\n' == all_file_lines[stop_LO]:
            stop_LO += 1

        return start_LO, stop_LO, bot
Esempio n. 6
0
def _subcommand_open(sin, sout, serr, argv, efx):
    """Open an issue"""

    prog_name = (bash_argv := list(reversed(argv))).pop()
    foz = _formals_via(_formals_for_open(), lambda: prog_name)
    vals, es = foz.terminal_parse(serr, bash_argv)
    if vals is None:
        return es

    if vals.get('help'):
        return foz.write_help_into(serr, _subcommand_open.__doc__)

    # == BEGIN experiment
    def listener(chan, *rest):
        if 'verbose' != chan:
            return mon.listener(chan, *rest)
        if not be_verbose:
            return
        mon.listener('info', *rest)
    be_verbose = vals.pop('verbose', False)
    # == END

    dct = {'main_tag': '#open', 'content': vals['message']}
    is_dry = vals.get('dry_run', False)
    opn = efx.produce_open_function()
    mon = efx.emission_monitor

    readme = efx.resolve_issues_file_path()
    if readme is None:
        return 4

    from pho._issues.edit import open_issue as func
    cs = func(readme, dct, listener, be_verbose=be_verbose, opn=opn)
    # cs = custom struct
    if cs is None:
        return mon.exitstatus

    dct = cs._asdict()
    if 'before_entity' in dct:
        before = dct.pop('before_entity')
        after = dct.pop('after_entity')
    else:
        before = None
        after = dct.pop('created_entity')

    if True:
        if before:
            serr.write(f"before: {before.to_line()}")
            serr.write(f"after:  {after.to_line()}")
        else:
            serr.write(f"line:   {after.to_line()}")

    efx.apply_patch(cs.diff_lines, is_dry, listener)  # result is t/f
    return mon.exitstatus
        def use_f(self):
            patch_file = self.big_patchfile.patches[n]

            from text_lib.diff_and_patch import \
                file_patches_via_unified_diff_lines as func
            _2 = func(patch_file.diff_lines)
            _1 = patch_file

            class these_two:  # #class-as-namespace
                patch_file = _1
                file_patch, = tuple(_2)

            return these_two
Esempio n. 8
0
def _counter_and_scanner_via_iterator(itr):
    from text_lib.magnetics.scanner_via import \
        scanner_via_iterator as func, MUTATE_add_counter
    scn = func(itr)
    count = MUTATE_add_counter(scn)
    return count, scn
Esempio n. 9
0
def _file_patches_via_patch_lines(lines):
    from text_lib.diff_and_patch import \
            file_patches_via_unified_diff_lines as func
    return tuple(func(lines))
Esempio n. 10
0
 def build_file_patch(self):
     lines = self.end_state['diff_lines']
     from text_lib.diff_and_patch import \
         file_patches_via_unified_diff_lines as func
     file_patch, = tuple(func(lines))
     return file_patch
Esempio n. 11
0
def _pass_thru_context_manager(lines):
    from contextlib import nullcontext as func
    return func(lines)
Esempio n. 12
0
def _error_monitor(serr):
    from script_lib.magnetics.error_monitor_via_stderr import func
    return func(serr, default_error_exitstatus=4)
Esempio n. 13
0
def _formals_via(defs, prog_namer, sub_commands=None):
    from script_lib.cheap_arg_parse import formals_via_definitions as func
    return func(defs, prog_namer, sub_commands)
Esempio n. 14
0
 def pieces(rec):
     return (func(rec) for func in cel_renderers)
Esempio n. 15
0
 def apply_patch(diff_lines, is_dry, listener):
     from text_lib.diff_and_patch import apply_patch_via_lines as func
     return func(diff_lines, is_dry, listener, cwd=None)  # t/f result
Esempio n. 16
0
        if readme_is_dash:
            # Read from stdin and each line is a readme path
            opened = sin
        else:
            # Open readme and each line is passed to the collection constructor
            opened = open(readme)
    elif readme_is_dash:
        # Pass stdin to open as the collection
        opened = _pass_thru_context_manager((sin,))
    else:
        # Pass the readme path to the collection
        opened = _pass_thru_context_manager((readme,))

    # Run the query
    from pho._issues import records_via_query_ as func
    itr = func(opened, user_query_tokens, sort_by, do_batch, mon.listener)
    two = next(itr)
    if two is None:
        return mon.returncode
    jsoner, counts = two

    # Prepare for output
    is_by_time = sort_by and 'by_time' == sort_by[0]
    is_complicated = do_batch or is_by_time
    # being "complicated" means needing strange columns

    if (fmt := vals.get('format')) is not None:
        allow = 'json', 'table'
        if fmt not in allow:
            _ = ''.join(('{', '|'.join(allow), '}'))
            inv = foz.invite_line