diff options
author | Sebastien Martini <seb@dbzteam.org> | 2010-01-03 15:04:28 +0100 |
---|---|---|
committer | Sebastien Martini <seb@dbzteam.org> | 2010-01-03 15:04:28 +0100 |
commit | 7bbd6dab1c317314161567a6088076282100f736 (patch) | |
tree | 4e3ebc4039e88b505e6df5aad60020284b92cb6b /python2 | |
parent | a8a70eeab092b89471435015196894ffb419bd97 (diff) | |
download | pyinotify-7bbd6dab1c317314161567a6088076282100f736.tar.gz |
- Removed custom glob functions, uses standard glob module directly.
- Modified exclusion filter mechanism, patterns still can be loaded
from files but the syntax has changed see exclude.lst for more
details. This new method is safer since the external file is not
executed anymore, it is only parsed looking for patterns loaded
as strings.
Diffstat (limited to 'python2')
-rw-r--r-- | python2/examples/exclude.lst | 12 | ||||
-rw-r--r-- | python2/examples/exclude.patterns | 16 | ||||
-rw-r--r-- | python2/examples/exclude.py | 35 | ||||
-rwxr-xr-x | python2/pyinotify.py | 111 |
4 files changed, 57 insertions, 117 deletions
diff --git a/python2/examples/exclude.lst b/python2/examples/exclude.lst new file mode 100644 index 0000000..7e81272 --- /dev/null +++ b/python2/examples/exclude.lst @@ -0,0 +1,12 @@ +# File associated to exclude.py +# +# List of patterns using regexps as defined into re standard module. +# These regexps are matched against submitted paths with re.match(). + +# Put only one pattern by line. +^/etc/apache[2]?/ +^/etc/rc.* +^/etc/hostname +^/etc/hosts +^/etc/(fs|m)tab +^/etc/cron\..* diff --git a/python2/examples/exclude.patterns b/python2/examples/exclude.patterns deleted file mode 100644 index f519b15..0000000 --- a/python2/examples/exclude.patterns +++ /dev/null @@ -1,16 +0,0 @@ -# -*- mode: python; -*- - -# Patterns can use unrestricted regexps (see re module) -# regexps are matched against submitted paths through match() - -excl_lst1 = ['^/etc/apache[2]?/', - '^/etc/rc.*', - '^/etc/hostname', - '^/etc/hosts', - '^/etc/(fs|m)tab', - '^/etc/cron\..*'] - -excl_lst2 = ['^/var/log/.*', - '^/var/www/.*', - '^/var/cache/.*', - '^/var/spool/.*'] diff --git a/python2/examples/exclude.py b/python2/examples/exclude.py index 850dbfe..4f12960 100644 --- a/python2/examples/exclude.py +++ b/python2/examples/exclude.py @@ -1,27 +1,30 @@ -# Example: excludes items from being monitored. +# Example: exclude items from being monitored. # -import pyinotify import os - -excl_file = os.path.join(os.getcwd(), 'exclude.patterns') +import pyinotify wm = pyinotify.WatchManager() notifier = pyinotify.Notifier(wm) - ### Method 1: -# Exclude filter object -excl = pyinotify.ExcludeFilter({excl_file: ('excl_lst1', 'excl_lst2')}) +# Exclude patterns from file +excl_file = os.path.join(os.getcwd(), 'exclude.lst') +excl = pyinotify.ExcludeFilter(excl_file) # Add watches -wm.add_watch(['/etc/*', '/var'], pyinotify.ALL_EVENTS, - rec=True, do_glob=True, exclude_filter=excl) - +res = wm.add_watch(['/etc/hostname', '/etc/cups', '/etc/rc0.d'], + pyinotify.ALL_EVENTS, rec=True, exclude_filter=excl) ### Method 2 (Equivalent) -wm.add_watch('/etc/*', pyinotify.ALL_EVENTS, rec=True, do_glob=True, - exclude_filter=pyinotify.ExcludeFilter({excl_file:('excl_lst1',)})) -wm.add_watch('/var', pyinotify.ALL_EVENTS, rec=True, - exclude_filter=pyinotify.ExcludeFilter({excl_file:('excl_lst2',)})) - +# Exclude patterns from list +excl_lst = ['^/etc/apache[2]?/', + '^/etc/rc.*', + '^/etc/hostname', + '^/etc/hosts', + '^/etc/(fs|m)tab', + '^/etc/cron\..*'] +excl = pyinotify.ExcludeFilter(excl_lst) +# Add watches +res = wm.add_watch(['/etc/hostname', '/etc/cups', '/etc/rc0.d'], + pyinotify.ALL_EVENTS, rec=True, exclude_filter=excl) -notifier.loop() +#notifier.loop() diff --git a/python2/pyinotify.py b/python2/pyinotify.py index 8a6111b..8cfe2ec 100755 --- a/python2/pyinotify.py +++ b/python2/pyinotify.py @@ -85,6 +85,7 @@ import re import ctypes import ctypes.util import asyncore +import glob try: from functools import reduce @@ -183,10 +184,7 @@ def logger_init(): log = logger_init() - -### inotify's variables ### - - +# inotify's variables class SysCtlINotify: """ Access (read, write) inotify's variables through sysctl. Usually it @@ -253,74 +251,6 @@ for attrname in ('max_queued_events', 'max_user_instances', 'max_user_watches'): globals()[attrname] = SysCtlINotify(attrname) - -### iglob ### - - -# Code taken from standart Python Lib, slightly modified in order to work -# with pyinotify (don't exclude dotted files/dirs like .foo). -# Original version: -# @see: http://svn.python.org/projects/python/trunk/Lib/glob.py - -def iglob(pathname): - if not has_magic(pathname): - if hasattr(os.path, 'lexists'): - if os.path.lexists(pathname): - yield pathname - else: - if os.path.islink(pathname) or os.path.exists(pathname): - yield pathname - return - dirname, basename = os.path.split(pathname) - # relative pathname - if not dirname: - return - # absolute pathname - if has_magic(dirname): - dirs = iglob(dirname) - else: - dirs = [dirname] - if has_magic(basename): - glob_in_dir = glob1 - else: - glob_in_dir = glob0 - for dirname in dirs: - for name in glob_in_dir(dirname, basename): - yield os.path.join(dirname, name) - -def glob1(dirname, pattern): - if not dirname: - dirname = os.curdir - try: - names = os.listdir(dirname) - except os.error: - return [] - return fnmatch.filter(names, pattern) - -def glob0(dirname, basename): - if basename == '' and os.path.isdir(dirname): - # `os.path.split()` returns an empty basename for paths ending with a - # directory separator. 'q*x/' should match only directories. - return [basename] - if hasattr(os.path, 'lexists'): - if os.path.lexists(os.path.join(dirname, basename)): - return [basename] - else: - if (os.path.islink(os.path.join(dirname, basename)) or - os.path.exists(os.path.join(dirname, basename))): - return [basename] - return [] - -MAGIC_CHECK = re.compile('[*?[]') - -def has_magic(s): - return MAGIC_CHECK.search(s) is not None - - - -### Core ### - - class EventsCodes: """ Set of codes corresponding to each kind of events. @@ -1501,14 +1431,20 @@ class ExcludeFilter: """ def __init__(self, arg_lst): """ + Examples: + ef1 = ExcludeFilter(["^/etc/rc.*", "^/etc/hostname"]) + ef2 = ExcludeFilter("/my/path/exclude.lst") + Where exclude.lst contains: + ^/etc/rc.* + ^/etc/hostname + @param arg_lst: is either a list or dict of patterns: - [pattern1, ..., patternn] - {'filename1': (list1, listn), ...} where list1 is - a list of patterns - @type arg_lst: list or dict + [pattern1, ..., patternn] or a filename from which + patterns will be loaded. + @type arg_lst: list(str) or str """ - if isinstance(arg_lst, dict): - lst = self._load_patterns(arg_lst) + if isinstance(arg_lst, str): + lst = self._load_patterns_from_file(arg_lst) elif isinstance(arg_lst, list): lst = arg_lst else: @@ -1518,13 +1454,18 @@ class ExcludeFilter: for regex in lst: self._lregex.append(re.compile(regex, re.UNICODE)) - def _load_patterns(self, dct): + def _load_patterns_from_file(self, filename): lst = [] - for path, varnames in dct.items(): - loc = {} - execfile(path, {}, loc) - for varname in varnames: - lst.extend(loc.get(varname, [])) + file_obj = file(filename, 'r') + try: + for line in file_obj.readlines(): + # Trim leading an trailing whitespaces + pattern = line.strip() + if not pattern or pattern.startswith('#'): + continue + lst.append(pattern) + finally: + file_obj.close() return lst def _match(self, regex, path): @@ -1656,7 +1597,7 @@ class WatchManager: def __glob(self, path, do_glob): if do_glob: - return iglob(path) + return glob.iglob(path) else: return [path] |