def setup_debugger():
    '''
    Rig up breakpoint() behavior based on the debugger option. Return True
    if we set up a debugger, False otherwise.
    '''

    if options.debugger not in SUPPORTED_DEBUGGERS:
        vd.status(f'Skipping setup for unknown debugger: {options.debugger}')
        return False

    debugger_env = {
        'remote-pdb': {
            'PYTHONBREAKPOINT': 'remote_pdb.set_trace',
            'REMOTE_PDB_HOST': '127.0.0.1',
            'REMOTE_PDB_PORT': '4444',
        },
        'pudb': {
            'PYTHONBREAKPOINT': 'pudb.set_trace',
        },
        'web-pdb': {
            'PYTHONBREAKPOINT': 'web_pdb.set_trace',
        },
    }

    os.environ.update(debugger_env[options.debugger])
    return True
 def _checkSelectedIndex(self):
     if self._selectedMask.index is not self.frame.index:
         # selection is no longer valid
         vd.status('frame.index updated, clearing {} selected rows'.format(
             self._selectedMask.sum()))
         self._selectedMask = Series.from_element(False,
                                                  index=self.frame.index)
def setup_debugger():
    """
    Rig up breakpoint() behavior based on the debugger option. Return True
    if we set up a debugger, False otherwise.
    """

    if vd.options.debugger not in SUPPORTED_DEBUGGERS:
        vd.status(
            f"Skipping setup for unknown debugger: {vd.options.debugger}")
        return False

    debugger_env = {
        "remote-pdb": {
            "PYTHONBREAKPOINT": "remote_pdb.set_trace",
            "REMOTE_PDB_HOST": "127.0.0.1",
            "REMOTE_PDB_PORT": "4444",
        },
        "pudb": {
            "PYTHONBREAKPOINT": "pudb.set_trace",
        },
        "web-pdb": {
            "PYTHONBREAKPOINT": "web_pdb.set_trace",
        },
    }

    os.environ.update(debugger_env[vd.options.debugger])
    return True
def goParentRow(_, by):
    """
    While focused in a child "detail" sheet, navigate through rows
    in the parent sheet.
    """

    parent = vd.sheets[1]
    newIndex = parent.cursorRowIndex + by
    if newIndex < 0:
        vd.status("Already at the top!")
        return
    elif newIndex >= len(parent.rows):
        vd.status("Already at the bottom!")
        return

    # The goal here is to navigate around a parent window in a consistent way,
    # updating a child view in the process. Find out whether the current
    # sheet represents a detail view of the cursor _row_ or _cell_ in the
    # parent sheet. Use that to determine how to update the child view.
    #
    # Edge case:
    #
    # * When scrolling through parent cells that would yield no child content
    #   (and therefore not open a sheet), we need a dummy stand-in sheet to
    #   keep the child window open and avoid breaking things. This happens
    #   when, for example, the parent cell is an empty list.
    for entityType in CHILD_ENTITY_TYPES:
        vs = _replaceDetailSheet(newIndex, entityType)
        if vs:
            break
Example #5
0
def unselect(self, rows, status=True, progress=True):
    "Unselect given rows. Don't show progress if progress=False; don't show status if status=False."
    self.addUndoSelection()
    before = self.nSelected
    for r in (Progress(rows, 'unselecting') if progress else rows):
        self.unselectRow(r)
    if status:
        vd.status('unselected %s/%s %s' %
                  (before - self.nSelected, before, self.rowtype))
Example #6
0
 def toggle_versioning(self):
     """Enable or disable support for S3 versioning."""
     self.version_aware = not self.version_aware
     self.fs.version_aware = self.version_aware
     vd.status(f's3 versioning {"enabled" if self.version_aware else "disabled"}')
     if self.currentThreads:
         vd.debug("cancelling threads before reloading")
         vd.cancelThread(*self.currentThreads)
     self.reload()
Example #7
0
def cursesMain(_scr, sheetlist):
    'Populate VisiData object with sheets from a given list.'

    colors.setup()

    for vs in sheetlist:
        vd.push(vs)

    vd.status('Ctrl+H opens help')
    return vd.mainloop(_scr)
    def deleteBy(self, by):
        '''Delete rows for which func(row) is true.  Returns number of deleted rows.'''
        # oldidx = self.cursorRowIndex # NOTE: not used
        nRows = self.nRows
        vd.addUndo(setattr, self, 'frame', self.frame)

        self.frame = self.frame[~by].reindex(IndexAutoFactory)
        ndeleted = nRows - self.nRows

        vd.status('deleted %s %s' % (ndeleted, self.rowtype))
        return ndeleted
Example #9
0
def select(self, rows, status=True, progress=True):
    "Bulk select given rows. Don't show progress if progress=False; don't show status if status=False."
    self.addUndoSelection()
    before = self.nSelected
    if options.bulk_select_clear:
        self.clearSelected()
    for r in (Progress(rows, 'selecting') if progress else rows):
        self.selectRow(r)
    if status:
        if options.bulk_select_clear:
            msg = 'selected %s %s%s' % (self.nSelected, self.rowtype,
                                        ' instead' if before > 0 else '')
        else:
            msg = 'selected %s%s %s' % (self.nSelected - before, ' more'
                                        if before > 0 else '', self.rowtype)
        vd.status(msg)
Example #10
0
def undo(vd, sheet):
    if not options.undo:
        vd.fail("options.undo not enabled")

    # don't allow undo of first command on a sheet, which is always the command that created the sheet.
    for cmdlogrow in sheet.cmdlog_sheet.rows[:0:-1]:
        if cmdlogrow.undofuncs:
            for undofunc, args, kwargs, in cmdlogrow.undofuncs:
                undofunc(*args, **kwargs)
            sheet.undone.append(cmdlogrow)
            sheet.cmdlog_sheet.rows.remove(cmdlogrow)
            vd.moveToReplayContext(cmdlogrow)
            vd.clearCaches()
            vd.status("%s undone" % cmdlogrow.longname)
            return

    vd.fail("nothing to undo on current sheet")
Example #11
0
 def setValues(self, rows, *values):
     'Set our column value for given list of rows to `value`.'
     vd.addUndoSetValues([self], rows)
     for r, v in zip(rows, itertools.cycle(values)):
         self.setValueSafe(r, v)
     self.recalc()
     return vd.status('set %d cells to %d values' %
                      (len(rows), len(values)))
Example #12
0
def getSheet(vd, sheetname):
    matchingSheets = [x for x in vd.sheets if x.name == sheetname]
    if matchingSheets:
        if len(matchingSheets) > 1:
            vd.status('more than one sheet named "%s"' % sheetname)
        return matchingSheets[0]

    try:
        sheetidx = int(sheetname)
        return vd.sheets[sheetidx]
    except ValueError:
        pass

    if sheetname == 'options':
        vs = self.optionsSheet
        vs.reload()
        vs.vd = vd
        return vs
def break_once(obj, func):
    """
    Wrap obj.func() to perform initial debugger setup and trigger a breakpoint.
    After one invocation, restore the original function.
    """

    f = getattr(obj, func)

    @wraps(f)
    def wrapper(*args, **kwargs):
        setup_debugger() and breakpoint() or vd.status(
            "Skipping debugger setup")
        f(*args, **kwargs)
        setattr(obj, func, f)
        vd.status(f"{func} function restored to original")

    setattr(obj, func, wrapper)
    vd.status(f"{func} function wrapped to initialize debugging")
Example #14
0
def zoomFreqtblRow(sheet, by):
    '''
    Navigate a frequency table sheet, "zooming in" on matching rows from the
    source sheet. Open matching rows in a disposable sheet one level up
    in the stack - while using a split view, this means the non-active
    window is a dedicated zoom pane.
    '''
    if sheet.cursorRowIndex == len(sheet.rows) - 1 and by == 1:
        vd.status('Already at the bottom!')
        return
    if sheet.cursorRowIndex == 0 and by == -1:
        vd.status('Already at the top!')
        return
    sheet.cursorDown(by)
    vs = sheet.openRow(sheet.cursorRow)
    vs.precious = False
    if sheet.source.source is vd.sheets[1].source and not vd.sheets[1].precious:
        vd.remove(vd.sheets[1])
    vd.sheets.insert(1, vs)
Example #15
0
def openurl_s3(p, filetype):
    """Open a sheet for an S3 path.

    S3 directories (prefixes) require special handling, but files (objects)
    can use standard VisiData "open" functions.
    """

    # Non-obvious behavior here: For the default case, we don't want to send
    # a custom endpoint to s3fs. However, using None as a default trips up
    # VisiData's type detection for the endpoint option. So we use an empty
    # string as the default instead, and convert back to None here.
    endpoint = vd.options.vds3_endpoint or None

    p = S3Path(
        str(p.given),
        version_aware=getattr(p, "version_aware", vd.options.vds3_version_aware),
        version_id=getattr(p, "version_id", None),
    )

    p.fs.version_aware = p.version_aware
    if p.fs.client_kwargs.get("endpoint_url", "") != endpoint:
        p.fs.client_kwargs = {"endpoint_url": endpoint}
        p.fs.connect()

    if not p.fs.isfile(str(p.given)):
        return S3DirSheet(p.name, source=p, version_aware=p.version_aware)

    if not filetype:
        filetype = p.ext or "txt"

    openfunc = getattr(vd, f"open_{filetype.lower()}")
    if not openfunc:
        vd.warning(f"no loader found for {filetype} files, falling back to txt")
        filetype = "txt"
        openfunc = vd.open_txt

    assert callable(openfunc), f"no function/method available to open {p.given}"
    vs = openfunc(p)
    vd.status(
        f'opening {p.given} as {filetype} (version id: {p.version_id or "latest"})'
    )
    return vs
Example #16
0
def goParentRow(sheet, by):
    '''
    While focused in a child "detail" split view, navigate through rows
    in the parent sheet.
    '''

    parent = vd.sheets[1]
    newIndex = parent.cursorRowIndex + by
    if newIndex < 0:
        vd.status('Already at the top!')
        return
    elif newIndex >= len(parent.rows):
        vd.status('Already at the bottom!')
        return

    if not NoContentPlaceholder.emptyRowSheet:
        NoContentPlaceholder.emptyRowSheet = load_pyobj(
            'placeholder', NoContentPlaceholder.emptyRowMessage)
    if not NoContentPlaceholder.emptyCellSheet:
        NoContentPlaceholder.emptyCellSheet = load_pyobj(
            'placeholder', NoContentPlaceholder.emptyCellMessage)

    # The goal here is to intelligently navigate around a parent window,
    # updating a child view in the process. Find out whether the current
    # sheet represents a detail view of the cursor _row_ or _cell_ in the
    # parent sheet. Use that to determine how to update the child view.
    #
    # Edge case:
    #
    # * When scrolling through parent cells that would yield no child content,
    #   we need a dummy stand-in sheet to keep the child window open.
    ChildUpdate = namedtuple('ChildUpdate',
                             'parentRowIdx openCommand placeholder')
    childUpdates = [
        ChildUpdate(newIndex, 'open-cell',
                    NoContentPlaceholder.emptyCellSheet),
        ChildUpdate(newIndex, 'open-row', NoContentPlaceholder.emptyRowSheet),
    ]
    for childUpdate in childUpdates:
        vs = _replaceDetailSheet(*childUpdate)
        if vs:
            break
Example #17
0
    def setValuesTyped(self, rows, *values):
        'Set values on this column for rows, coerced to the column type.  will stop on first exception in type().'
        vd.addUndoSetValues([self], rows)
        for r, v in zip(rows,
                        itertools.cycle(self.type(val) for val in values)):
            self.setValueSafe(r, v)

        self.recalc()

        return vd.status('set %d cells to %d values' %
                         (len(rows), len(values)))
Example #18
0
def select_duplicate_rows(sheet, duplicates=True):
    """
    Given a sheet, sets the selection status in VisiData to `selected` for each
    row that is a duplicate of a prior row.

    If `duplicates = False`, then the behavior is reversed; sets the selection
    status to `selected` for each row that is *not* a duplicate.
    """
    before = len(sheet.selectedRows)

    gen = gen_identify_duplicates(sheet)
    prog = Progress(gen, gerund="selecting", total=sheet.nRows)

    for row, is_dupe in prog:
        if is_dupe == duplicates:
            sheet.selectRow(row)

    sel_count = len(sheet.selectedRows) - before

    more_str = " more" if before > 0 else ""

    vd.status(f"selected {sel_count}{more_str} {sheet.rowtype}")
Example #19
0
def createPillowImage(dwg):
    im = Image.new("RGB", (640, 480), color=(0, 0, 0))

    draw = ImageDraw.Draw(im)
    font = ImageFont.truetype(dwg.options.darkdraw_font,
                              dwg.options.darkdraw_font_size)

    vd.clearCaches()
    dwg._scr = mock.MagicMock(__bool__=mock.Mock(return_value=True),
                              getmaxyx=mock.Mock(return_value=(9999, 9999)))
    dwg.draw(dwg._scr)

    displayed = set()
    for y in range(dwg.minY, dwg.maxY + 1):
        for x in range(dwg.minX, dwg.maxX + 1):
            rows = dwg._displayedRows.get((x, y), None)
            if not rows: continue
            r = rows[-1]
            k = str(r)
            if k in displayed: continue
            if not r.text: continue
            if x - r.x >= len(r.text): continue
            i = x - r.x
            s = r.text[i:]
            fg, bg, attrs = colors.split_colorstr(r.color)
            c = termcolor_to_rgb(fg)
            xy = ((r.x + i) * 8, r.y * 16)
            if bg:
                draw.rectangle((xy, (xy[0] + 16, xy[1] + 8)),
                               fill=termcolor_to_rgb(bg))
            draw.text(xy, s, font=font, fill=c)
            if 'underline' in attrs:
                draw.line((xy, (xy[0] + 16, xy[1])), fill=c)
                draw.line(((xy[0], xy[1] + 8), (xy[0] + 16, xy[1] + 8)),
                          fill=c)
            displayed.add(k)

    vd.status(' '.join(displayed))
    return im
Example #20
0
def select_duplicate_rows(sheet, duplicates = True):
    """
    Given a sheet, sets the selection status in VisiData to `selected` for each
    row that is a duplicate of a prior row.

    If `duplicates = False`, then the behavior is reversed; sets the selection
    status to `selected` for each row that is *not* a duplicate.
    """
    before = len(sheet.selectedRows)

    for row, is_dupe in gen_identify_duplicates(sheet):
        if is_dupe == duplicates:
            sheet.selectRow(row)

    sel_count = len(sheet.selectedRows) - before

    more_str = " more" if before > 0 else ""

    vd.status("selected {}{} {}".format(
        sel_count,
        more_str,
        sheet.rowtype
    ))
    Try to guess an appropriate vfake faketype for a given column and row set.
    If we find a match, run with it. NO REGERTS.
    """

    isNull = _isNullFunc()
    for col in cols:
        faketype = None
        with suppress(StopIteration):
            sample_value = next(hint for r in rows
                                if not isNull(hint := col.getValue(r)))
            faketype = next(v for k, v in faketype_mapping.items()
                            if k(str(sample_value), col.name))
        if not faketype:
            vd.warning(f"Could not detect a fake type for column {col.name}")
            continue
        vd.status(f"Detected fake type {faketype} for column {col.name}")
        vd.addUndoSetValues([col], rows)
        col.setValuesFromFaker(faketype, rows)


BaseSheet.bindkey("zf", "setcol-fake")
BaseSheet.addCommand(
    "gzf",
    "setcol-fake-all",
    'cursorCol.setValuesFromFaker(vd.input("faketype: ", type="faketype"), rows)',
)
BaseSheet.addCommand("z^F", "setcol-autofake",
                     "sheet.autofake([cursorCol], rows)")
BaseSheet.addCommand("gz^F", "setcols-autofake",
                     "sheet.autofake(columns, rows)")
Example #22
0
def warning(vd, *args):
    vd.status(*args, priority=1)
Example #23
0
def mainloop(self, scr):
    'Manage execution of keystrokes and subsequent redrawing of screen.'
    scr.timeout(curses_timeout)
    with contextlib.suppress(curses.error):
        curses.curs_set(0)

    numTimeouts = 0
    prefixWaiting = False
    vd.scrFull = scr

    self.keystrokes = ''
    while True:
        if not self.sheets:
            # if no more sheets, exit
            return

        sheet = self.sheets[0]
        threading.current_thread().sheet = sheet
        vd.drawThread = threading.current_thread()

        sheet.ensureLoaded()

        vd.setWindows(scr)

        self.draw(vd.win1, self.sheets[0])
        if vd.win2 and len(self.sheets) > 1:
            self.draw(vd.win2, self.sheets[1])
        else:
            vd.win2.erase()
            vd.win2.refresh()

        keystroke = self.getkeystroke(scr, sheet)

        if not keystroke and prefixWaiting and ESC in self.keystrokes:  # timeout ESC
            self.keystrokes = ''

        if keystroke:  # wait until next keystroke to clear statuses and previous keystrokes
            numTimeouts = 0
            if not prefixWaiting:
                self.keystrokes = ''

            self.statuses.clear()

            if keystroke == 'KEY_MOUSE':
                self.keystrokes = ''
                clicktype = ''
                try:
                    devid, x, y, z, bstate = curses.getmouse()
                    sheet.mouseX, sheet.mouseY = x, y
                    if bstate & curses.BUTTON_CTRL:
                        clicktype += "CTRL-"
                        bstate &= ~curses.BUTTON_CTRL
                    if bstate & curses.BUTTON_ALT:
                        clicktype += "ALT-"
                        bstate &= ~curses.BUTTON_ALT
                    if bstate & curses.BUTTON_SHIFT:
                        clicktype += "SHIFT-"
                        bstate &= ~curses.BUTTON_SHIFT

                    keystroke = clicktype + curses.mouseEvents.get(
                        bstate, str(bstate))

                    f = self.getMouse(scr, x, y, keystroke)
                    if f:
                        if isinstance(f, str):
                            for cmd in f.split():
                                sheet.exec_keystrokes(cmd)
                        else:
                            f(y, x, keystroke)

                        self.keystrokes = keystroke
                        keystroke = ''
                except curses.error:
                    pass
                except Exception as e:
                    self.exceptionCaught(e)

            if keystroke in self.keystrokes[:-1]:
                vd.warning('duplicate prefix')
                self.keystrokes = ''
            else:
                self.keystrokes += keystroke

        self.drawRightStatus(sheet._scr,
                             sheet)  # visible for commands that wait for input

        if not keystroke:  # timeout instead of keypress
            pass
        elif keystroke == '^Q':
            return self.lastErrors and '\n'.join(self.lastErrors[-1])
        elif vd.bindkeys._get(self.keystrokes):
            sheet.exec_keystrokes(self.keystrokes)
            prefixWaiting = False
        elif keystroke in self.allPrefixes:
            prefixWaiting = True
        else:
            vd.status('no command for "%s"' % (self.keystrokes))
            prefixWaiting = False

        self.checkForFinishedThreads()
        sheet.checkCursorNoExceptions()

        # no idle redraw unless background threads are running
        time.sleep(0)  # yield to other threads which may not have started yet
        if vd.unfinishedThreads:
            scr.timeout(curses_timeout)
        else:
            numTimeouts += 1
            if numTimeouts > timeouts_before_idle:
                scr.timeout(-1)
            else:
                scr.timeout(curses_timeout)
    '''
    Try to guess an appropriate vfake faketype for a given column and row set.
    If we find a match, run with it. NO REGERTS.
    '''

    isNull = isNullFunc()
    for col in cols:
        faketype = None
        with suppress(StopIteration):
            next(r for r in rows if not isNull(hint := col.getValue(r)))
            faketype = next(v for k, v in faketype_mapping.items()
                            if k(str(hint), col.name))
        if not faketype:
            vd.warning(f'Could not detect a fake type for column {col.name}')
            continue
        vd.status(f'Detected fake type {faketype} for column {col.name}')
        vd.addUndoSetValues([col], rows)
        col.setValuesFromFaker(faketype, rows)


BaseSheet.bindkey("zf", "setcol-fake")
BaseSheet.addCommand(
    "gzf",
    "setcol-fake-all",
    'cursorCol.setValuesFromFaker(input("faketype: ", type="faketype"), rows)',
)
BaseSheet.addCommand('z^F', 'setcol-autofake',
                     f'{__name__}.autofake([cursorCol], rows)')
BaseSheet.addCommand('gz^F', 'setcols-autofake',
                     f'{__name__}.autofake(columns, rows)')
Example #25
0
def redo(vd, sheet):
    sheet.undone or vd.fail("nothing to redo")
    cmdlogrow = sheet.undone.pop()
    vd.replayOne(cmdlogrow)
    vd.status("%s redone" % cmdlogrow.longname)
Example #26
0
def error(vd, *args):
    'Log an error and raise an exception.'
    vd.status(*args, priority=3)
    raise ExpectedException(args[0] if args else '')
 def wrapper(*args, **kwargs):
     setup_debugger() and breakpoint() or vd.status(
         "Skipping debugger setup")
     f(*args, **kwargs)
     setattr(obj, func, f)
     vd.status(f"{func} function restored to original")
Example #28
0
def fail(vd, *args):
    vd.status(*args, priority=2)
    raise ExpectedException(args[0] if args else '')
Example #29
0
def debug(vd, *args, **kwargs):
    if options.debug:
        return vd.status(*args, **kwargs)