14 signal
.signal(signal
.SIGIO
, self
.fire
)
17 if not self
.installed
:
19 signal
.signal(signal
.SIGIO
, signal
.SIG_DFL
)
21 def add(self
, watcher
):
22 self
.watchers
[watcher
.fd
.fileno()] = watcher
24 def remove(self
, watcher
):
25 if self
.watchers
.has_key(watcher
.fd
.fileno()):
26 del(self
.watchers
[watcher
.fd
.fileno()])
29 def fire(self
, signum
, frame
):
30 # this is the signal handler
31 # without siginfo_t, we must fire them all
32 for watcher
in self
.watchers
.values():
36 DN_ACCESS
= fcntl
.DN_ACCESS
# a file in the directory was read
37 DN_MODIFY
= fcntl
.DN_MODIFY
# a file was modified (write,truncate)
38 DN_CREATE
= fcntl
.DN_CREATE
# a file was created
39 DN_DELETE
= fcntl
.DN_DELETE
# a file was unlinked
40 DN_RENAME
= fcntl
.DN_RENAME
# a file was renamed
41 DN_ATTRIB
= fcntl
.DN_ATTRIB
# a file had attributes changed (chmod,chown)
45 def __init__(self
, dirname
, callback
=None,
46 flags
=[DN_MODIFY
,DN_CREATE
,DN_DELETE
,DN_RENAME
]):
48 """This object watches a directory for changes. The .callback
49 attribute should be set to a function to be run every time something
50 happens to it. Be aware that it will be called more times than you
54 self
.callback
= callback
56 self
.callback
= self
.fire
57 self
.dirname
= dirname
58 self
.flags
= reduce(lambda x
, y
: x | y
, flags
) | fcntl
.DN_MULTISHOT
59 self
.fd
= open(dirname
, "r")
60 # ideally we would move the notification to something like SIGRTMIN,
61 # (to free up SIGIO) and use sigaction to have the signal handler
62 # receive a structure with the fd number. But python doesn't offer
64 if not self
.handler
[0]:
65 self
.handler
[0] = DNotify_Handler()
66 self
.handler
[0].add(self
)
67 fcntl
.fcntl(self
.fd
, fcntl
.F_NOTIFY
, self
.flags
)
69 self
.handler
[0].remove(self
)
72 print self
.dirname
, "changed!"
80 # create ./foo/, create/delete files in ./ and ./foo/ while this is
81 # running. Notice how both notifiers are fired when anything changes;
82 # this is an unfortunate side-effect of the lack of extended sigaction
86 def fire1(count
=count
, d1
=d1
):
87 print "./ changed!", count
[0]
92 # change the callback, since we can't define it until after we have the
93 # dnotify object. Hmm, unless we give the dnotify to the callback.
95 def fire2(): print "foo/ changed!"
96 d2
= DNotify("foo", fire2
)
101 if __name__
== '__main__':