Source code for track.utils.delay

[docs]class FutureIsNotReady(Exception): pass
[docs]class Future: def __init__(self, promise): self.promise = promise
[docs] def get(self): return self.promise.returned
[docs] def is_ready(self): return self.get() is not None
def __getattr__(self, item): """ if the attribute does not exist we evaluate the partial call and execute that attribute """ value = self.get() if value is None: raise FutureIsNotReady() return getattr(self.get(), item)
[docs]class DelayedCall: """Delay a call until later""" def __init__(self, fun, kwargs): self.fun = fun self.kwargs = kwargs self.returned = None self.is_processing = False def __call__(self, *args, **kwargs): if self.returned is None and self.is_processing: raise RuntimeError('Circular dependencies') if self.returned is None: self.kwargs.update(kwargs) self.is_processing = True self.returned = self.fun(**self.kwargs) self.is_processing = False return self.returned else: return self.returned(*args, **kwargs)
[docs] def add_arguments(self, **kwargs): self.kwargs.update(kwargs)
[docs] def get_future(self): return Future(self)
def __getattr__(self, item): """ if the attribute does not exist we evaluate the partial call and execute that attribute """ if self.returned is None and self.is_processing: raise RuntimeError('Circular dependencies') if self.returned is None: self.is_processing = True self.returned = self.fun(**self.kwargs) self.is_processing = False return getattr(self.returned, item)
[docs]def delay_call(fun, **kwargs): return DelayedCall(fun, kwargs)
[docs]def is_delayed_call(obj): return isinstance(obj, DelayedCall) and obj.returned is None