Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
| """General programming utils, inclined toward functional programming. | |
| If ever a function changes its input in place, it is denoted by a trailing `_` | |
| """ | |
| import inspect | |
| from itertools import zip_longest | |
| from typing import List, Set, Union, Dict | |
| def ifnone(*xs): | |
| """Return the first item in 'x' that is not None""" | |
| for x in xs: | |
| if x is not None: return x | |
| return None | |
| def custom_dir(c, add): return dir(type(c)) + list(c.__dict__.keys()) + add | |
| class GetAttr: | |
| """Base class for attr accesses in `self._xtra` passed down to `self.default` | |
| Taken from article by Jeremy Howard: https://www.fast.ai/2019/08/06/delegation/ | |
| Usage: | |
| ``` | |
| class ProductPage(GetAttr): | |
| def __init__(self, page, price, cost): | |
| self.page,self.price,self.cost = page,price,cost | |
| self.default = page | |
| ``` | |
| """ | |
| def _xtra(self): return [o for o in dir(self.default) if not o.startswith('_')] | |
| def __getattr__(self,k): | |
| if k in self._xtra: return getattr(self.default, k) | |
| raise AttributeError(k) | |
| def __dir__(self): return custom_dir(self, self._xtra) | |
| # Can i delegate many different functions? | |
| # Can i add a new docstring to the existing docstring of the delgated function? Or at least point to the function delegated? | |
| def delegates(to=None, keep=False): | |
| """ Decorator: replace `**kwargs` in signature with params from `to`. | |
| Taken from article by Jeremy Howard: https://www.fast.ai/2019/08/06/delegation/ | |
| """ | |
| def _f(f): | |
| if to is None: to_f,from_f = f.__base__.__init__,f.__init__ | |
| else: to_f,from_f = to,f | |
| sig = inspect.signature(from_f) | |
| sigd = dict(sig.parameters) | |
| k = sigd.pop('kwargs') | |
| s2 = {k:v for k,v in inspect.signature(to_f).parameters.items() | |
| if v.default != inspect.Parameter.empty and k not in sigd} | |
| sigd.update(s2) | |
| if keep: sigd['kwargs'] = k | |
| from_f.__signature__ = sig.replace(parameters=sigd.values()) | |
| return f | |
| return _f | |
| def pick(keys:Union[List, Set], obj:Dict) -> Dict: | |
| """ Return a NEW object containing `keys` from the original `obj` """ | |
| return {k: obj[k] for k in keys} | |
| def memoize(f): | |
| """Memoize a function. | |
| Use lookup table when the same inputs are passed to the function instead of running that function again | |
| """ | |
| memo = {} | |
| def helper(*x): | |
| if x not in memo: | |
| memo[x] = f(*x) | |
| return memo[x] | |
| return helper | |
| def assoc(k, v, orig): | |
| """Given an original dictionary orig, return a cloned dictionary with `k` set to `v`""" | |
| out = orig.copy() | |
| out[k] = v | |
| return out | |
| def make_unique(f): | |
| """The input function will only run and return if it hasn't seen its argument before. | |
| Otherwise, it will return `None`. | |
| """ | |
| s = set() | |
| def helper(x): | |
| if x in s: | |
| return None | |
| s.add(x) | |
| return f(x) | |
| return helper | |
| def flatten_(items, seqtypes=(list, tuple)): | |
| """Flattten an arbitrarily nested list IN PLACE""" | |
| for i, x in enumerate(items): | |
| while i < len(items) and isinstance(items[i], seqtypes): | |
| items[i:i+1] = items[i] | |
| return items |