|
@@ -13,10 +13,27 @@ import sys
|
|
|
import time
|
|
|
import select
|
|
|
import hashlib
|
|
|
+import threading
|
|
|
|
|
|
from collections import defaultdict
|
|
|
|
|
|
from .. import current_app
|
|
|
+from ..abstract import StartStopComponent
|
|
|
+
|
|
|
+
|
|
|
+class WorkerComponent(StartStopComponent):
|
|
|
+ name = "worker.autoreloader"
|
|
|
+ requires = ("pool", )
|
|
|
+
|
|
|
+ def __init__(self, w, **kwargs):
|
|
|
+ self.enabled = w.autoreload
|
|
|
+ w.autoreloader = None
|
|
|
+
|
|
|
+ def create(self, w):
|
|
|
+ w.autoreloader = self.instantiate(w.autoreloader_cls,
|
|
|
+ modules=w.autoreload,
|
|
|
+ logger=w.logger)
|
|
|
+ return w.autoreloader
|
|
|
|
|
|
|
|
|
def file_hash(filename, algorithm='md5'):
|
|
@@ -151,11 +168,16 @@ else:
|
|
|
_monitor_cls = StatMonitor
|
|
|
|
|
|
|
|
|
-class AutoReloader(object):
|
|
|
+class AutoReloader(threading.Thread):
|
|
|
"""Tracks changes in modules and fires reload commands"""
|
|
|
- def __init__(self, modules, monitor_cls=_monitor_cls, *args, **kwargs):
|
|
|
- self._monitor = monitor_cls(modules, self.on_change, *args, **kwargs)
|
|
|
- self._hashes = dict([(f, file_hash(f)) for f in modules])
|
|
|
+ def __init__(self, modules, monitor_cls=_monitor_cls, logger=None,
|
|
|
+ *args, **kwargs):
|
|
|
+ super(AutoReloader, self).__init__()
|
|
|
+ self.daemon = True
|
|
|
+ self.logger = logger
|
|
|
+ files = [sys.modules[m].__file__ for m in modules]
|
|
|
+ self._monitor = monitor_cls(files, self.on_change, *args, **kwargs)
|
|
|
+ self._hashes = dict([(f, file_hash(f)) for f in files])
|
|
|
|
|
|
def start(self):
|
|
|
self._monitor.start()
|
|
@@ -168,6 +190,8 @@ class AutoReloader(object):
|
|
|
modified.append(f)
|
|
|
self._hashes[f] = fhash
|
|
|
if modified:
|
|
|
+ self.logger.debug("Detected modified modules: %s" %\
|
|
|
+ map(self._module_name, modified))
|
|
|
self._reload(map(self._module_name, modified))
|
|
|
|
|
|
def _reload(self, modules):
|
|
@@ -177,3 +201,7 @@ class AutoReloader(object):
|
|
|
@classmethod
|
|
|
def _module_name(cls, path):
|
|
|
return os.path.splitext(os.path.basename(path))[0]
|
|
|
+
|
|
|
+ def stop(self):
|
|
|
+ if hasattr(self._monitor, 'stop'):
|
|
|
+ self._monitor.stop()
|