From 4f5f4383042976a9971943287e28a6b0b83140fc Mon Sep 17 00:00:00 2001 From: Peerchemist Date: Wed, 23 Jan 2019 14:54:38 +0100 Subject: [PATCH] fix module importing --- build/lib/timeloop/__init__.py | 1 + build/lib/timeloop/app.py | 65 ++++++++++++++++++++++++++++++++ build/lib/timeloop/exceptions.py | 6 +++ build/lib/timeloop/helpers.py | 4 ++ build/lib/timeloop/job.py | 19 ++++++++++ 5 files changed, 95 insertions(+) create mode 100644 build/lib/timeloop/__init__.py create mode 100644 build/lib/timeloop/app.py create mode 100644 build/lib/timeloop/exceptions.py create mode 100644 build/lib/timeloop/helpers.py create mode 100644 build/lib/timeloop/job.py diff --git a/build/lib/timeloop/__init__.py b/build/lib/timeloop/__init__.py new file mode 100644 index 0000000..8d95c4d --- /dev/null +++ b/build/lib/timeloop/__init__.py @@ -0,0 +1 @@ +from timeloop.app import Timeloop diff --git a/build/lib/timeloop/app.py b/build/lib/timeloop/app.py new file mode 100644 index 0000000..d6808d1 --- /dev/null +++ b/build/lib/timeloop/app.py @@ -0,0 +1,65 @@ +import logging +import sys +import signal +import time + +from timeloop.exceptions import ServiceExit +from timeloop.job import Job +from timeloop.helpers import service_shutdown + + +class Timeloop(): + def __init__(self): + self.jobs = [] + logger = logging.getLogger('timeloop') + ch = logging.StreamHandler(sys.stdout) + ch.setLevel(logging.INFO) + formatter = logging.Formatter('[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s') + ch.setFormatter(formatter) + logger.addHandler(ch) + logger.setLevel(logging.INFO) + self.logger = logger + + def _add_job(self, func, interval, *args, **kwargs): + j = Job(interval, func, *args, **kwargs) + self.jobs.append(j) + + def _block_main_thread(self): + signal.signal(signal.SIGTERM, service_shutdown) + signal.signal(signal.SIGINT, service_shutdown) + + while True: + try: + time.sleep(1) + except ServiceExit: + self.stop() + break + + def _start_jobs(self, block): + for j in self.jobs: + j.daemon = not block + j.start() + self.logger.info("Registered job {}".format(j.execute)) + + def _stop_jobs(self): + for j in self.jobs: + self.logger.info("Stopping job {}".format(j.execute)) + j.stop() + + def job(self, interval): + def decorator(f): + self._add_job(f, interval) + return f + return decorator + + def stop(self): + self._stop_jobs() + self.logger.info("Timeloop exited.") + + def start(self, block=False): + self.logger.info("Starting Timeloop..") + self._start_jobs(block=block) + + self.logger.info("Timeloop now started. Jobs will run based on the interval set") + if block: + self._block_main_thread() diff --git a/build/lib/timeloop/exceptions.py b/build/lib/timeloop/exceptions.py new file mode 100644 index 0000000..4585852 --- /dev/null +++ b/build/lib/timeloop/exceptions.py @@ -0,0 +1,6 @@ +class ServiceExit(Exception): + """ + Custom exception which is used to trigger the clean exit + of all running threads and the main program. + """ + pass diff --git a/build/lib/timeloop/helpers.py b/build/lib/timeloop/helpers.py new file mode 100644 index 0000000..01b22e8 --- /dev/null +++ b/build/lib/timeloop/helpers.py @@ -0,0 +1,4 @@ +from timeloop.exceptions import ServiceExit + +def service_shutdown(signum, frame): + raise ServiceExit diff --git a/build/lib/timeloop/job.py b/build/lib/timeloop/job.py new file mode 100644 index 0000000..df97d2f --- /dev/null +++ b/build/lib/timeloop/job.py @@ -0,0 +1,19 @@ +from threading import Thread, Event +from datetime import timedelta + +class Job(Thread): + def __init__(self, interval, execute, *args, **kwargs): + Thread.__init__(self) + self.stopped = Event() + self.interval = interval + self.execute = execute + self.args = args + self.kwargs = kwargs + + def stop(self): + self.stopped.set() + self.join() + + def run(self): + while not self.stopped.wait(self.interval.total_seconds()): + self.execute(*self.args, **self.kwargs)