1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
| #!/usr/bin/env python
# -*- coding: utf-8 -*-
##############################################################################
# AutoReload Process Using inofify
# wangbuke <wangbuke@gmail.com>
# taken from https://github.com/stevekrenzel/autoreload
#
# To use autoreload:
# 1. Make sure the script is executable by running chmod +x autoreload
# 2. Run ./autoreload <path> <ext1,ext2,extn> <cmd>
# e.g: $ ./autoreload '.' '.py,.xml,.conf' './openerp-server -c openerp-server.conf'
#
##############################################################################
import os
import signal
import subprocess
import sys
import time
import pyinotify
from pyinotify import log
class ReloadNotifier(pyinotify.Notifier):
def loop(self, callback=None, daemonize=False, **args):
if daemonize:
self.__daemonize(**args)
# Read and process events forever
while 1:
try:
self._default_proc_fun._print_stdout()
self.process_events()
if (callback is not None) and (callback(self) is True):
break
ref_time = time.time()
# check_events is blocking
if self.check_events():
self._sleep(ref_time)
self.read_events()
except KeyboardInterrupt:
# Stop monitoring if sigint is caught (Control-C).
log.debug('Pyinotify stops monitoring.')
self._default_proc_fun._stop_process()
break
# Close internals
self.stop()
class OnChangeHandler(pyinotify.ProcessEvent):
def my_init(self, cwd, extension, cmd):
self.cwd = cwd
self.extensions = extension.split(',')
self.cmd = cmd
self.process = None
self._start_process()
def _start_process(self):
self.process = subprocess.Popen(self.cmd, shell=True, preexec_fn=os.setsid)
def _stop_process(self):
os.killpg(self.process.pid, signal.SIGTERM)
self.process.wait()
def _restart_process(self):
print '==> Modification detected, restart process. <=='
self._stop_process()
self._start_process()
def _print_stdout(self):
stdout = self.process.stdout
if stdout != None:
print stdout
def process_IN_CREATE(self, event):
if any(event.pathname.endswith(ext) for ext in self.extensions) or "IN_ISDIR" in event.maskname:
self._restart_process()
def process_IN_DELETE(self, event):
if any(event.pathname.endswith(ext) for ext in self.extensions) or "IN_ISDIR" in event.maskname:
self._restart_process()
def process_IN_CLOSE_WRITE(self, event):
if any(event.pathname.endswith(ext) for ext in self.extensions) or "IN_ISDIR" in event.maskname:
self._restart_process()
def process_IN_MOVED_FROM(self, event):
if any(event.pathname.endswith(ext) for ext in self.extensions) or "IN_ISDIR" in event.maskname:
self._restart_process()
def process_IN_MOVED_TO(self, event):
if any(event.pathname.endswith(ext) for ext in self.extensions) or "IN_ISDIR" in event.maskname:
self._restart_process()
def autoreload(path, extension, cmd):
wm = pyinotify.WatchManager()
handler = OnChangeHandler(cwd=path, extension=extension, cmd=cmd)
notifier = ReloadNotifier(wm, default_proc_fun=handler)
mask = pyinotify.IN_CLOSE_WRITE | pyinotify.IN_MOVED_FROM | pyinotify.IN_MOVED_TO | pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_DELETE_SELF | pyinotify.IN_MOVE_SELF
wm.add_watch(path, mask, rec=True, auto_add=True)
print '==> Start monitoring %s (type c^c to exit) <==' % path
notifier.loop()
if __name__ == '__main__':
path = sys.argv[1]
extension = sys.argv[2]
cmd = sys.argv[3]
autoreload(path, extension, cmd)
|