Source code for visidata.wrappers

'value wrappers for nulls and errors'

from copy import copy
import functools

from visidata import options, stacktrace, BaseSheet, vd


[docs] @BaseSheet.api def isNullFunc(sheet): 'Return func(value) which returns whether or not *value* is null.' nullv = sheet.options.null_value if nullv is None: return lambda v: v is None or isinstance(v, TypedWrapper) return lambda v, nullv=nullv: v is None or v == nullv or isinstance(v, TypedWrapper)
@functools.total_ordering class TypedWrapper: def __init__(self, func, *args): self.type = func self.args = args self.val = args[0] if args else '' def __bool__(self): return False def __len__(self): return 0 def __repr__(self): return '%s(%s)' % (self.type.__name__, ','.join(str(x) for x in self.args)) def __str__(self): if self.val is None: return '' return repr(self) def __lt__(self, x): 'maintain sortability; wrapped objects are always least' return True def __add__(self, x): return x def __radd__(self, x): return x def __hash__(self): return hash((self.type, str(self.val))) def __eq__(self, x): if isinstance(x, TypedWrapper): return self.type == x.type and self.val == x.val return self.val == x # a wrapped None compares equal to None #3112 def __iter__(self): return self def __next__(self): raise StopIteration class TypedExceptionWrapper(TypedWrapper): def __init__(self, func, *args, exception=None): TypedWrapper.__init__(self, func, *args) self.exception = exception self.stacktrace = stacktrace() self.forwarded = False def __str__(self): return str(self.exception) def __hash__(self): return hash((type(self.exception), ''.join(self.stacktrace[:-1]))) def __eq__(self, x): if isinstance(x, TypedExceptionWrapper): return type(self.exception) is type(x.exception) and self.stacktrace[:-1] == x.stacktrace[:-1] def forward(wr): if isinstance(wr, TypedExceptionWrapper): wr.forwarded = True return wr def wrmap(func, iterable, *args): 'Same as map(func, iterable, *args), but ignoring exceptions.' for it in iterable: try: yield func(it, *args) except Exception: pass def wrapply(func, *args, **kwargs): 'Like apply(), but which wraps Exceptions and passes through Wrappers (if first arg)' if args: val = args[0] if val is None: # None values propagate to TypedWrappers return TypedWrapper(func, None) elif isinstance(val, TypedExceptionWrapper): # previous Exceptions propagate, marked 'forwarded' tew = copy(val) tew.forwarded = True return tew elif isinstance(val, TypedWrapper): # TypedWrappers (likely None, from above) propagate return val elif isinstance(val, Exception): # Exception values become TypedWrappers return TypedWrapper(func, *args) try: return func(*args, **kwargs) except Exception as e: e.stacktrace = stacktrace() return TypedExceptionWrapper(func, *args, exception=e) vd.addGlobals( forward=forward, wrmap=wrmap, wrapply=wrapply, TypedWrapper=TypedWrapper, TypedExceptionWrapper=TypedExceptionWrapper )