def _inner(fun: PushFunction) -> PushFunction: validator.is_function(fun=fun) def _call(self: 'Push', envelope: Optional[Envelope] = None, payload: Payload = None, **kwargs: Any) -> Payload: validator.is_instance(Push, self=self) parsed = self._parse_envelope_value(value, envelope=envelope) new_kwargs = {value: parsed, 'payload': payload} if envelope is not None: new_kwargs['envelope'] = envelope return fun(self, **{**new_kwargs, **kwargs}) if asyncio.iscoroutinefunction(fun): @functools.wraps(fun) async def _wrapper(self: 'Push', envelope: Optional[Envelope] = None, payload: Payload = None, **kwargs: Any) -> Payload: return await _call(self, envelope, payload, **kwargs) return _wrapper return functools.wraps(fun)(_call)
def _parse_envelope_value( self, name: str, envelope: Optional[Envelope] = None, parse_fun: Optional[Callable[[Any], Any]] = None, instance_lookup_fun: Optional[Callable[..., Optional[Any]]] = None) -> Any: """ Parse the envelope for the given `name`. If present in the envelope the extracted value will be tested / parsed by the given `parse_fun`. If no `parse_fun` is explicitly given, it will be determined if this instance provides a `parse_<name>`, `_parse_<name>` or a `__parse_<name>`. If yes the function is called; otherwise the value is returned as is. If the value is not present in the envelope the current instance will be probed for `<name>`, `_<name>` or `__<name>`. If an instance variable is present it will be returned unvalidated / unparsed (we assume that happened previously). If no variable is present simply `None` will be returned. Args: name: Name of the attribute to lookup in the envelope / instance. envelope: Envelope of the payload. parse_fun: Custom function to validate / parse. If not given it will be determined automagically. instance_lookup_fun: Custom function to perform instance variable lookups. If not given a reasonably default will be used. """ validator.is_instance(str, name=name) validator.is_instance(dict, allow_none=True, envelope=envelope) if parse_fun: validator.is_function(parse_fun=parse_fun) if instance_lookup_fun: validator.is_function(instance_lookup_fun=instance_lookup_fun) lookups = cast( Dict[str, str], utils.make_public_protected_private_attr_lookup(name, as_dict=True)) if envelope is None or name not in envelope: return (instance_lookup_fun(name) if instance_lookup_fun is not None else _lookup(self, list(lookups.values())) # pylint: disable=no-member ) val = envelope[name] try: if parse_fun is None: public_attr_name = lookups['public'] # pylint: disable=invalid-sequence-index fun_base = 'parse_' + public_attr_name parse_fun_names = utils.make_public_protected_private_attr_lookup( fun_base) parse_fun = _lookup(self, parse_fun_names) if parse_fun is None: return val return parse_fun(val) except (ValueError, TypeError): self.logger.exception("Cannot parse value for '%s' from envelope", name) return (instance_lookup_fun(name) if instance_lookup_fun is not None else _lookup(self, list(lookups.values())) # pylint: disable=no-member )
def __init__(self, fun: Callable[..., Any], cool_down: float = 0.5, cool_down_callback: Optional[Callable[[], None]] = None, renew_cooldown: bool = True): super().__init__(fun, cool_down) if cool_down_callback: validator.is_function(cool_down_callback=cool_down_callback) self.cool_down_callback = cool_down_callback self.renew_cooldown = bool(renew_cooldown)
async def async_sleep_until_interrupt(sleep_time: float, interrupt_fun: SleepInterruptPredicate, interval: float = 0.1) -> None: """Call this method to sleep an interruptable sleep until the interrupt co-routine returns True.""" validator.is_function(interrupt_fun=interrupt_fun) async def callback() -> None: if await interrupt_fun(): raise StopCycleError() await async_interruptible_sleep(sleep_time, callback, interval=interval)
def sleep_until_interrupt(sleep_time: float, interrupt_fun: Callable[[], bool], interval: float = 0.5) -> None: """Call this method to sleep an interruptable sleep until the interrupt function returns True.""" validator.is_function(interrupt_fun=interrupt_fun) def callback() -> None: if interrupt_fun(): raise StopCycleError() interruptable_sleep(sleep_time, callback, interval=interval)
def enveloped(fun: PushFunction) -> Callable[['Push', Payload], Payload]: """Decorator to split the envelope and the actual payload. This is an but a convenience decorator for `envelope_payload` of the `PushBase` class.""" validator.is_function(fun=fun) def _call(self: 'Push', payload: Payload) -> Payload: validator.is_instance(Push, self=self) envelope, real_payload = self.envelope_payload(payload) return fun(self, envelope=envelope, payload=real_payload) if asyncio.iscoroutinefunction(fun): @functools.wraps(fun) async def _wrapper(self: 'Push', payload: Payload) -> Payload: return await _call(self, payload) return _wrapper return functools.wraps(fun)(_call)
def __init__(self, fun: Callable[..., Any], wait: float = 0.5): validator.is_function(fun=fun) self.fun = fun self.wait = float(wait) self.timer = None # type: Optional[Timer]
def __init__(self, scheduled_callable, **kwargs): super().__init__(**kwargs) self.scheduled_callable = scheduled_callable validator.is_function(scheduled_callable=self.scheduled_callable)