def openRepl(self): """Open a ptipython-based REPL that inherits VisiData's context.""" try: # Provide local top-level access to VisiData global and sheet-local # variables, similar to VisiData's `execCommand` context. new_locals = LazyChainMap(Dummy(), vd, vd.sheet) locals().update(new_locals) except Exception as e: vd.exceptionCaught(e) with SuspendCurses(): try: history_file = (Path(vd.options.visidata_dir).expanduser() / "cache" / "ptpython" / "history") Path.mkdir(history_file.parent, parents=True, exist_ok=True) shell = InteractiveShellEmbed.instance( history_filename=str(history_file), vi_mode=True, ) shell.python_input.title = "VisiData IPython REPL (ptipython)" shell.python_input.show_exit_confirmation = False embed() except Exception as e: vd.exceptionCaught(e) finally: # The embedded IPython session is a singleton by default, # but launching it via `open-repl` in VisiData a second time # seems to either freeze or leave an exit message up from the # previous instance. Clean out the existing instance so any # future invocations get a fresh start. InteractiveShellEmbed.clear_instance()
def openRepl(self): orig_stdin = sys.stdin orig_stdout = sys.stdout try: # Provide local top-level access to VisiData global and sheet-local # variables, similar to VisiData's `execCommand` context. new_locals = LazyChainMap(Dummy(), vd, vd.sheet) locals().update(new_locals) except Exception as e: vd.exceptionCaught(e) with SuspendCurses(): try: sys.stdin = vd._stdin sys.stdout = open('/dev/tty', mode='w') history_file = (Path(vd.options.visidata_dir).expanduser() / 'cache' / 'ptpython' / 'history') Path.mkdir(history_file.parent, parents=True, exist_ok=True) shell = InteractiveShellEmbed.instance( history_filename=str(history_file), vi_mode=True, ) shell.python_input.title = 'VisiData IPython REPL (ptipython)' shell.python_input.show_exit_confirmation = False embed() except Exception as e: vd.exceptionCaught(e) finally: sys.stdin = orig_stdin sys.stdout = orig_stdout
def addRegexColumns(regexMaker, vs, colIndex, origcol, regexstr): regexstr or vd.fail('regex required') regex = re.compile(regexstr, vs.regex_flags()) func = regexMaker(regex, origcol) n = options.default_sample_size if n and n < len(vs.rows): exampleRows = random.sample(vs.rows, max( 0, n - 1)) # -1 to account for included cursorRow else: exampleRows = vs.rows ncols = 0 # number of new columns added already for r in Progress(exampleRows + [vs.cursorRow]): try: m = func(r) if not m: continue except Exception as e: vd.exceptionCaught(e) for _ in range(len(m) - ncols): c = Column( origcol.name + '_re' + str(ncols), getter=lambda col, row, i=ncols, func=func: func(row)[i], origCol=origcol) vs.addColumn(c, index=colIndex + ncols + 1) ncols += 1
def checkMemoryUsage(vd): min_mem = options.min_memory_mb threads = vd.unfinishedThreads if not threads: return None ret = '' attr = 'color_working' if min_mem: try: freestats = subprocess.run( 'free --total --mega'.split(), check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.strip().splitlines() except FileNotFoundError as e: if options.debug: vd.exceptionCaught(e) options.min_memory_mb = 0 warning('disabling min_memory_mb: "free" not installed') return '', attr tot_m, used_m, free_m = map(int, freestats[-1].split()[1:]) ret = '[%dMB] ' % free_m + ret if free_m < min_mem: attr = 'color_warning' warning('%dMB free < %dMB minimum, stopping threads' % (free_m, min_mem)) cancelThread(*vd.unfinishedThreads) curses.flash() return ret, attr
def drawLeftStatus(vd, scr, vs): 'Draw left side of status bar.' cattr = colors.get_color('color_status') active = vs is vd.sheets[0] # active sheet if active: cattr = update_attr(cattr, colors.color_active_status, 0) else: cattr = update_attr(cattr, colors.color_inactive_status, 0) if scr is vd.winTop: cattr = update_attr(cattr, colors.color_top_status, 1) attr = cattr.attr error_attr = update_attr(cattr, colors.color_error, 1).attr warn_attr = update_attr(cattr, colors.color_warning, 2).attr sep = options.disp_status_sep x = 0 y = vs.windowHeight - 1 # status for each window try: lstatus = vs.leftStatus() maxwidth = options.disp_lstatus_max if maxwidth > 0: lstatus = middleTruncate(lstatus, maxwidth // 2) x = clipdraw(scr, y, 0, lstatus, attr, w=vs.windowWidth - 1) vd.onMouse(scr, y, 0, 1, x, BUTTON1_PRESSED='sheets', BUTTON3_PRESSED='rename-sheet', BUTTON3_CLICKED='rename-sheet') except Exception as e: vd.exceptionCaught(e) if not active: return one = False for (pri, msgparts), n in sorted(vd.statuses.items(), key=lambda k: -k[0][0]): try: if x > vs.windowWidth: break if one: # any messages already: x += clipdraw(scr, y, x, sep, attr, w=vs.windowWidth - x) one = True msg = composeStatus(msgparts, n) if pri == 3: msgattr = error_attr elif pri == 2: msgattr = warn_attr elif pri == 1: msgattr = warn_attr else: msgattr = attr x += clipdraw(scr, y, x, msg, msgattr, w=vs.windowWidth - x) except Exception as e: vd.exceptionCaught(e)
def drawRightStatus(vd, scr, vs): 'Draw right side of status bar. Return length displayed.' rightx = vs.windowWidth ret = 0 statcolors = [ (vd.rightStatus(vs), 'color_status'), ] active = vs is vd.sheets[0] # active sheet if active: statcolors.append((vd.keystrokes, 'color_keystrokes')) if vs.currentThreads: statcolors.insert(0, vd.checkMemoryUsage()) if vs.progresses: gerund = vs.progresses[0].gerund else: gerund = 'processing' statcolors.insert(1, (' %s %s…' % (vs.progressPct, gerund), 'color_status')) if active and vd.currentReplay: statcolors.insert(0, (vd.replayStatus, 'color_status_replay')) for rstatcolor in statcolors: if rstatcolor: try: rstatus, coloropt = rstatcolor rstatus = ' ' + rstatus cattr = colors.get_color(coloropt) if scr is vd.winTop: cattr = update_attr(cattr, colors.color_top_status, 0) if active: cattr = update_attr(cattr, colors.color_active_status, 0) else: cattr = update_attr(cattr, colors.color_inactive_status, 0) statuslen = clipdraw(scr, vs.windowHeight - 1, rightx, rstatus, cattr.attr, w=vs.windowWidth - 1, rtl=True) rightx -= statuslen ret += statuslen except Exception as e: vd.exceptionCaught(e) if scr: curses.doupdate() return ret
def loadConfigFile(fnrc, _globals=None): p = visidata.Path(fnrc) if _globals is None: _globals = globals() if p.exists(): try: code = compile(open(p).read(), str(p), 'exec') exec(code, _globals) except Exception as e: vd.exceptionCaught(e) addGlobals(_globals)
def _colorize(self, col, row, value=None) -> ColorAttr: 'Returns ColorAttr for the given colorizers/col/row/value' colorstack = [] for colorizer in self.allColorizers: try: r = colorizer.func(self, col, row, value) if r: colorstack.append(colorizer.coloropt if colorizer.coloropt else r) except Exception as e: vd.exceptionCaught(e) return colors.resolve_colors(tuple(colorstack))
def SI(n): if not isinstance(n, (int, float)): return n orig_n = n try: level = 0 while n > 1000: n /= 1000 level += 1 return '%0.1f%s' % (n, si_levels[level]) except Exception as e: vd.exceptionCaught(e) return orig_n
def _toplevelTryFunc(func, *args, status=status, **kwargs): with ThreadProfiler(threading.current_thread()) as prof: t = threading.current_thread() t.name = func.__name__ try: t.status = func(*args, **kwargs) except EscapeException as e: # user aborted t.status = 'aborted by user' if status: status('%s aborted' % t.name, priority=2) except Exception as e: t.exception = e t.status = 'exception' vd.exceptionCaught(e) if t.sheet: t.sheet.currentThreads.remove(t)
def sort(self): 'Sort rows according to the current self._ordering.' try: with Progress(gerund='sorting', total=self.nRows) as prog: def sortkey(r): ret = [] for col, reverse in self._ordering: if isinstance(col, str): col = self.column(col) val = col.getTypedValue(r) ret.append(Reversor(val) if reverse else val) prog.addProgress(1) return ret # must not reassign self.rows: use .sort() instead of sorted() self.rows.sort(key=sortkey) except TypeError as e: vd.warning('sort incomplete due to TypeError; change column type') vd.exceptionCaught(e, status=False)
def exec_command(self, cmd, args='', vdglobals=None, keystrokes=None): "Execute `cmd` tuple with `vdglobals` as globals and this sheet's attributes as locals. Returns True if user cancelled." if not cmd: vd.debug('no command "%s"' % keystrokes) return True escaped = False err = '' if vdglobals is None: vdglobals = getGlobals() self.sheet = self try: if vd.cmdlog: vd.cmdlog.beforeExecHook(self, cmd, '', keystrokes) code = compile(cmd.execstr, cmd.longname, 'exec') vd.debug(cmd.longname) exec(code, vdglobals, LazyChainMap(vd, self)) except EscapeException as e: # user aborted vd.warning(str(e)) escaped = True except Exception as e: vd.debug(cmd.execstr) err = vd.exceptionCaught(e) escaped = True try: if vd.cmdlog: # sheet may have changed vd.cmdlog.afterExecSheet(vd.sheets[0] if vd.sheets else None, escaped, err) except Exception as e: vd.exceptionCaught(e) self.checkCursorNoExceptions() vd.clearCaches() return escaped
def sync(self, *joiningThreads): 'Wait for joiningThreads to finish. If no joiningThreads specified, wait for all but current thread and interface thread to finish.' joiningThreads = set(joiningThreads) while True: deads = set() # dead threads threads = joiningThreads or set(self.unfinishedThreads) threads -= set( [threading.current_thread(), getattr(vd, 'drawThread', None)]) threads -= deads for t in threads: try: if not t.is_alive(): deads.add(t) else: t.join() except RuntimeError as e: # maybe thread hasn't started yet or has already joined vd.exceptionCaught(e) pass if len(threads - deads) == 0: break
def setValueSafe(self, row, value): 'setValue and ignore exceptions' try: return self.setValue(row, value) except Exception as e: vd.exceptionCaught(e)
def checkCursorNoExceptions(self): try: return self.checkCursor() except Exception as e: vd.exceptionCaught(e)