Skip to content

Instantly share code, notes, and snippets.

@geekscrapy
Created April 23, 2020 08:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geekscrapy/052f8b7b10d5ef1347a35f6329efd4f2 to your computer and use it in GitHub Desktop.
Save geekscrapy/052f8b7b10d5ef1347a35f6329efd4f2 to your computer and use it in GitHub Desktop.
from visidata import *
option(name='delta_timedelta', default='days=1', helpstr='delta between date columns. This should be in the timedelta kwarg format such as days=1, or hours=3')
option(name='delta_nocase', default=True, helpstr='compare keycol strings ignoring case')
option(name='delta_round_timedelta', default=True, helpstr='draw a line where the time delta is rounded down. The delta will be rounded down')
option(name='delta_int', default=0, helpstr='delta between integers/floats for cpmparison')
option(name='delta_nKeyCols', default=-1, helpstr='number of keyColumns to compare. -1 is all')
theme('color_delta', 'underline', 'color of a row which is different to the one below')
dt_unit_order = ['year', 'month', 'day', 'hour', 'minute', 'second', 'microsecond']
def deltaColorizer(sheet, col, row, cellval):
## Give up if there are no keycolumns - speeds up loaders without default keycols
if len(sheet.keyCols) <= 0: return False
## Get the next row, unless we are at the end
try: next_row = sheet.rows[sheet.rows.index(row)+1]
except: return False
## Lists of the keycol values we compare later to eval if they match
curr_values = []
next_values = []
if options.delta_nKeyCols == -1:
considerCols = sheet.keyCols
else:
considerCols = sheet.keyCols[:options.delta_nKeyCols]
## Setup the date replacements now, for speed
delta_unit, delta_val = options.delta_timedelta.split('=')[0], int(options.delta_timedelta.split('=')[1])
dt_unit_i = dt_unit_order.index(delta_unit[:-1])+1
built_dt_replace = dict([(unit,0) for unit in dt_unit_order[dt_unit_i:]])
for kc in considerCols:
override = False
c_value = kc.getTypedValue(row)
n_value = kc.getTypedValue(next_row)
if type(c_value) in [TypedExceptionWrapper, TypedWrapper]:
override = True
## Compare ranges of ints/dates
elif kc.type in [int, date]:
if kc.type == int:
margin = int(options.delta_int)
elif kc.type == date and options.delta_round_timedelta:
## This nulls the datetime units (day/hour/min) that are rounded
## to the required delta (options.delta_date_unit)
margin = datetime.timedelta(**{delta_unit: delta_val})
c_value = c_value.replace(**built_dt_replace)
n_value = n_value.replace(**built_dt_replace)
if not(abs(c_value - n_value) >= margin):
override = True
if not override:
curr_values.append( str(kc.getDisplayValue(row)).lower() if options.delta_nocase else str(kc.getDisplayValue(row)) )
next_values.append( str(kc.getDisplayValue(next_row)).lower() if options.delta_nocase else str(kc.getDisplayValue(next_row)) )
else:
curr_values.append(override)
next_values.append(override)
return curr_values != next_values
# @functools.lru_cache(100)
# def delta_compare(c_value, n_value):
# return True, True
@Sheet.api
def DeltaColorizer(sheet, enable=True):
c = RowColorizer(8, 'color_delta', deltaColorizer)
if enable:
if not c in sheet.allColorizers:
sheet.addColorizer(c)
vd.addUndo(sheet.removeColorizer, c)
else:
try: sheet.removeColorizer(c)
except ValueError: status('already disabled')
Sheet.addCommand(None, 'delta-enable', 'DeltaColorizer(True)', helpstr='Enable delta')
Sheet.addCommand(None, 'delta-disable', 'DeltaColorizer(False)', helpstr='Disable delta')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment