diff options
author | Sebastien Martini <seb@dbzteam.org> | 2009-11-17 02:05:03 +0100 |
---|---|---|
committer | Sebastien Martini <seb@dbzteam.org> | 2009-11-17 02:05:03 +0100 |
commit | b3dc4c39dcb26d9e6863b6457248db4ca69e3332 (patch) | |
tree | 5a17998a47421de716d3bebbedbde27ce13607ae | |
parent | a398d07592a7fb7fe9c1a6b0d5bfd9c90d849431 (diff) | |
download | pyinotify-b3dc4c39dcb26d9e6863b6457248db4ca69e3332.tar.gz |
Modified exclusion filter code (contributed with Matteo Lanza
matteo.lanza@gmail.com):
- exclude_filter is now checked against auto-added directories
(created or moved).
- exclude_filter is now transmitted from parent directory to
auto-added directories (created or moved).
- Monitored transient files are cannot be excluded through
exclude_filter.
Removed "magic" keyworded arguments from Watch's constructor.
-rwxr-xr-x | python2/pyinotify.py | 71 | ||||
-rwxr-xr-x | python3/pyinotify.py | 79 |
2 files changed, 95 insertions, 55 deletions
diff --git a/python2/pyinotify.py b/python2/pyinotify.py index ccdd5b9..c93f0f4 100755 --- a/python2/pyinotify.py +++ b/python2/pyinotify.py @@ -666,25 +666,27 @@ class _SysProcessEvent(_ProcessEvent): """ if raw_event.mask & IN_ISDIR: watch_ = self._watch_manager.get_watch(raw_event.wd) - if watch_.auto_add: + created_dir = os.path.join(watch_.path, raw_event.name) + if watch_.auto_add and not watch_.exclude_filter(created_dir): addw = self._watch_manager.add_watch - newwd = addw(os.path.join(watch_.path, raw_event.name), - watch_.mask, proc_fun=watch_.proc_fun, - rec=False, auto_add=watch_.auto_add) + # The newly monitored directory inherits attributes from its + # parent directory. + newwd = addw(created_dir, watch_.mask, proc_fun=watch_.proc_fun, + rec=False, auto_add=watch_.auto_add, + exclude_filter=watch_.exclude_filter) # Trick to handle mkdir -p /t1/t2/t3 where t1 is watched and # t2 and t3 are created. # Since the directory is new, then everything inside it # must also be new. - base = os.path.join(watch_.path, raw_event.name) - if newwd[base] > 0: - for name in os.listdir(base): - inner = os.path.join(base, name) + if newwd[created_dir] > 0: + for name in os.listdir(created_dir): + inner = os.path.join(created_dir, name) if (os.path.isdir(inner) and self._watch_manager.get_wd(inner) is None): # Generate (simulate) creation event for sub # directories. - rawevent = _RawEvent(newwd[base], + rawevent = _RawEvent(newwd[created_dir], IN_CREATE | IN_ISDIR, 0, name) self._notifier.append_event(rawevent) @@ -718,12 +720,16 @@ class _SysProcessEvent(_ProcessEvent): # to provide as additional information to the IN_MOVED_TO event # the original pathname of the moved file/directory. to_append['src_pathname'] = mv_[0] - elif raw_event.mask & IN_ISDIR and watch_.auto_add: + elif (raw_event.mask & IN_ISDIR and watch_.auto_add and + not watch_.exclude_filter(dst_path)): # We got a diretory that's "moved in" from an unknown source and # auto_add is enabled. Manually add watches to the inner subtrees. + # The newly monitored directory inherits attributes from its + # parent directory. self._watch_manager.add_watch(dst_path, watch_.mask, proc_fun=watch_.proc_fun, - rec=True, auto_add=True) + rec=True, auto_add=True, + exclude_filter=watch_.exclude_filter) return self.process_default(raw_event, to_append) def process_IN_MOVE_SELF(self, raw_event): @@ -1163,7 +1169,8 @@ class Notifier: while rsum < queue_size: s_size = 16 # Retrieve wd, mask, cookie and fname_len - wd, mask, cookie, fname_len = struct.unpack('iIII', r[rsum:rsum+s_size]) + wd, mask, cookie, fname_len = struct.unpack('iIII', + r[rsum:rsum+s_size]) # Retrieve name fname, = struct.unpack('%ds' % fname_len, r[rsum + s_size:rsum + s_size + fname_len]) @@ -1433,7 +1440,7 @@ class Watch: Represent a watch, i.e. a file or directory being watched. """ - def __init__(self, **keys): + def __init__(self, wd, path, mask, proc_fun, auto_add, exclude_filter): """ Initializations. @@ -1447,9 +1454,17 @@ class Watch: @type proc_fun: @param auto_add: Automatically add watches on new directories. @type auto_add: bool - """ - for k, v in keys.items(): - setattr(self, k, v) + @param exclude_filter: Boolean function, used to exclude new + directories from being automatically watched. + See WatchManager.__init__ + @type exclude_filter: callable object + """ + self.wd = wd + self.path = path + self.mask = mask + self.proc_fun = proc_fun + self.auto_add = auto_add + self.exclude_filter = exclude_filter self.dir = os.path.isdir(self.path) def __repr__(self): @@ -1553,7 +1568,7 @@ class WatchManager: path must be excluded from being watched. Convenient for providing a common exclusion filter for every call to add_watch. - @type exclude_filter: bool + @type exclude_filter: callable object """ self._exclude_filter = exclude_filter self._wmd = {} # watch dict key: watch descriptor, value: watch @@ -1601,7 +1616,7 @@ class WatchManager: """ return self._wmd - def __add_watch(self, path, mask, proc_fun, auto_add): + def __add_watch(self, path, mask, proc_fun, auto_add, exclude_filter): """ Add a watch on path, build a Watch object and insert it in the watch manager dictionary. Return the wd value. @@ -1622,7 +1637,8 @@ class WatchManager: if wd_ < 0: return wd_ watch_ = Watch(wd=wd_, path=os.path.normpath(byte_path), mask=mask, - proc_fun=proc_fun, auto_add=auto_add) + proc_fun=proc_fun, auto_add=auto_add, + exclude_filter=exclude_filter) self._wmd[wd_] = watch_ log.debug('New %s', watch_) return wd_ @@ -1666,11 +1682,12 @@ class WatchManager: @param quiet: if False raises a WatchManagerError exception on error. See example not_quiet.py. @type quiet: bool - @param exclude_filter: boolean function, returns True if current - path must be excluded from being watched. - Has precedence on exclude_filter defined - into __init__. - @type exclude_filter: bool + @param exclude_filter: predicate (boolean function), which returns + True if the current path must be excluded + from being watched. This argument has + precedence over exclude_filter passed to + the class' constructor. + @type exclude_filter: callable object @return: dict of paths associated to watch descriptors. A wd value is positive if the watch was added sucessfully, otherwise the value is negative. If the path was invalid @@ -1691,7 +1708,8 @@ class WatchManager: if not exclude_filter(rpath): wd = ret_[rpath] = self.__add_watch(rpath, mask, proc_fun, - auto_add) + auto_add, + exclude_filter) if wd < 0: err = 'add_watch: cannot watch %s (WD=%d)' err = err % (rpath, wd) @@ -1950,7 +1968,8 @@ class WatchManager: return self.add_watch(dirname, mask, proc_fun=proc_class(ChainIfTrue(func=cmp_name)), rec=False, - auto_add=False, do_glob=False) + auto_add=False, do_glob=False, + exclude_filter=lambda path: False) class Color: diff --git a/python3/pyinotify.py b/python3/pyinotify.py index 29a52ae..f40ba18 100755 --- a/python3/pyinotify.py +++ b/python3/pyinotify.py @@ -631,25 +631,27 @@ class _SysProcessEvent(_ProcessEvent): """ if raw_event.mask & IN_ISDIR: watch_ = self._watch_manager.get_watch(raw_event.wd) - if watch_.auto_add: + created_dir = os.path.join(watch_.path, raw_event.name) + if watch_.auto_add and not watch_.exclude_filter(created_dir): addw = self._watch_manager.add_watch - newwd = addw(os.path.join(watch_.path, raw_event.name), - watch_.mask, proc_fun=watch_.proc_fun, - rec=False, auto_add=watch_.auto_add) + # The newly monitored directory inherits attributes from its + # parent directory. + newwd = addw(created_dir, watch_.mask, proc_fun=watch_.proc_fun, + rec=False, auto_add=watch_.auto_add, + exclude_filter=watch_.exclude_filter) # Trick to handle mkdir -p /t1/t2/t3 where t1 is watched and # t2 and t3 are created. # Since the directory is new, then everything inside it # must also be new. - base = os.path.join(watch_.path, raw_event.name) - if newwd[base] > 0: - for name in os.listdir(base): - inner = os.path.join(base, name) + if newwd[created_dir] > 0: + for name in os.listdir(created_dir): + inner = os.path.join(created_dir, name) if (os.path.isdir(inner) and self._watch_manager.get_wd(inner) is None): # Generate (simulate) creation event for sub # directories. - rawevent = _RawEvent(newwd[base], + rawevent = _RawEvent(newwd[created_dir], IN_CREATE | IN_ISDIR, 0, name) self._notifier.append_event(rawevent) @@ -683,12 +685,16 @@ class _SysProcessEvent(_ProcessEvent): # to provide as additional information to the IN_MOVED_TO event # the original pathname of the moved file/directory. to_append['src_pathname'] = mv_[0] - elif raw_event.mask & IN_ISDIR and watch_.auto_add: + elif (raw_event.mask & IN_ISDIR and watch_.auto_add and + not watch_.exclude_filter(dst_path)): # We got a diretory that's "moved in" from an unknown source and # auto_add is enabled. Manually add watches to the inner subtrees. + # The newly monitored directory inherits attributes from its + # parent directory. self._watch_manager.add_watch(dst_path, watch_.mask, proc_fun=watch_.proc_fun, - rec=True, auto_add=True) + rec=True, auto_add=True, + exclude_filter=watch_.exclude_filter) return self.process_default(raw_event, to_append) def process_IN_MOVE_SELF(self, raw_event): @@ -1125,7 +1131,8 @@ class Notifier: while rsum < queue_size: s_size = 16 # Retrieve wd, mask, cookie and fname_len - wd, mask, cookie, fname_len = struct.unpack('iIII', r[rsum:rsum+s_size]) + wd, mask, cookie, fname_len = struct.unpack('iIII', + r[rsum:rsum+s_size]) # Retrieve name bname, = struct.unpack('%ds' % fname_len, r[rsum + s_size:rsum + s_size + fname_len]) @@ -1391,7 +1398,7 @@ class Watch: Represent a watch, i.e. a file or directory being watched. """ - def __init__(self, **keys): + def __init__(self, wd, path, mask, proc_fun, auto_add, exclude_filter): """ Initializations. @@ -1405,9 +1412,17 @@ class Watch: @type proc_fun: @param auto_add: Automatically add watches on new directories. @type auto_add: bool - """ - for k, v in keys.items(): - setattr(self, k, v) + @param exclude_filter: Boolean function, used to exclude new + directories from being automatically watched. + See WatchManager.__init__ + @type exclude_filter: callable object + """ + self.wd = wd + self.path = path + self.mask = mask + self.proc_fun = proc_fun + self.auto_add = auto_add + self.exclude_filter = exclude_filter self.dir = os.path.isdir(self.path) def __repr__(self): @@ -1511,7 +1526,7 @@ class WatchManager: path must be excluded from being watched. Convenient for providing a common exclusion filter for every call to add_watch. - @type exclude_filter: bool + @type exclude_filter: callable object """ self._exclude_filter = exclude_filter self._wmd = {} # watch dict key: watch descriptor, value: watch @@ -1559,7 +1574,7 @@ class WatchManager: """ return self._wmd - def __add_watch(self, path, mask, proc_fun, auto_add): + def __add_watch(self, path, mask, proc_fun, auto_add, exclude_filter): """ Add a watch on path, build a Watch object and insert it in the watch manager dictionary. Return the wd value. @@ -1579,7 +1594,8 @@ class WatchManager: if wd_ < 0: return wd_ watch_ = Watch(wd=wd_, path=os.path.normpath(path), mask=mask, - proc_fun=proc_fun, auto_add=auto_add) + proc_fun=proc_fun, auto_add=auto_add, + exclude_filter=exclude_filter) self._wmd[wd_] = watch_ log.debug('New %s', watch_) return wd_ @@ -1620,11 +1636,12 @@ class WatchManager: @param quiet: if False raises a WatchManagerError exception on error. See example not_quiet.py. @type quiet: bool - @param exclude_filter: boolean function, returns True if current - path must be excluded from being watched. - Has precedence on exclude_filter defined - into __init__. - @type exclude_filter: bool + @param exclude_filter: predicate (boolean function), which returns + True if the current path must be excluded + from being watched. This argument has + precedence over exclude_filter passed to + the class' constructor. + @type exclude_filter: callable object @return: dict of paths associated to watch descriptors. A wd value is positive if the watch was added sucessfully, otherwise the value is negative. If the path was invalid @@ -1649,8 +1666,9 @@ class WatchManager: for rpath in self.__walk_rec(apath, rec): if not exclude_filter(rpath): wd = ret_[rpath] = self.__add_watch(rpath, mask, - proc_fun, - auto_add) + proc_fun, + auto_add, + exclude_filter) if wd < 0: err = 'add_watch: cannot watch %s (WD=%d)' err = err % (rpath, wd) @@ -1745,9 +1763,11 @@ class WatchManager: if mask: addw = LIBC.inotify_add_watch - # apath is always stored as unicode string so encode it to bytes. + # apath is always stored as unicode string so encode it to + # bytes. byte_path = apath.encode(sys.getfilesystemencoding()) - wd_ = addw(self._fd, ctypes.create_string_buffer(byte_path), mask) + wd_ = addw(self._fd, ctypes.create_string_buffer(byte_path), + mask) if wd_ < 0: ret_[awd] = False err = 'update_watch: cannot update WD=%d (%s)' % (wd_, @@ -1911,7 +1931,8 @@ class WatchManager: return self.add_watch(dirname, mask, proc_fun=proc_class(ChainIfTrue(func=cmp_name)), rec=False, - auto_add=False, do_glob=False) + auto_add=False, do_glob=False, + exclude_filter=lambda path: False) class Color: |