from traceback import format_exc from asyncio import sleep,create_task from datetime import datetime from asyncio import iscoroutinefunction,get_event_loop from . import utils class Timer(): def __init__(self,function,interval,block=None,start=None,*args,**kwargs): self.function=function self.interval=interval self.args=args self.kwargs=kwargs self.block=block if block is None: self.block=(interval == 0) self.start=start self.scheduled=None @property def isasync(self): return iscoroutinefunction(self.function) """ This mess of functions... Operate and enqueue are just wrappers that do some useful things that I couldn't fit elsewhere. Iterate is the core that runs them in the right order according to blocking. """ async def enqueue(self,interval=None): self.scheduled=create_task(self.iterate(interval)) async def operate(self,*args,**kwargs): if not args: args=self.args if not kwargs: kwargs=self.kwargs try: if not self.isasync: return self.function(*args,**kwargs) return await self.function(*args,**kwargs) except: utils.trace('explosions in',self); format_exc() async def iterate(self,interval=None): if interval is None: interval=self.interval await sleep(interval) await (self.operate,self.enqueue)[not self.block]() await (self.operate,self.enqueue)[self.block]() async def run(self): slop=0 if self.start is not None: ima=datetime.utcnow() slop=(self.start-ima).total_seconds() # It'll be very slightly wrong but whatever await self.enqueue(slop) def __str__(self): return self.function.__name__ def __del__(self): self.scheduled.cancel()