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