def __init__(self, ignore=None, debug=False): Pseudo.__init__(self, ignore=ignore, debug=debug) self.wm = pyinotify.WatchManager() self.notifier = pyinotify.ThreadedNotifier(self.wm, self) self.notifier.start() self.event_filter = dict() self.watches_by_path = dict()
def start(self): Pseudo.start(self) self.watchmgr = pyinotify.WatchManager() self.notifier = pyinotify.ThreadedNotifier(self.watchmgr, self) self.notifier.start() for monitor in self.add_q: self.AddMonitor(*monitor) self.add_q = []
def __init__(self, ignore=None, debug=False): Pseudo.__init__(self, ignore=ignore, debug=debug) pyinotify.ProcessEvent.__init__(self) self.event_filter = dict() self.watches_by_path = dict() # these are created in start() after the server is done forking self.notifier = None self.watchmgr = None self.add_q = []
def start(self): """ The inotify notifier and manager objects in :attr:`notifier` and :attr:`watchmgr` must be created by the daemonized process, so they are created in ``start()``. Before those objects are created, monitors are added to :attr:`add_q`, and are created once the :class:`pyinotify.ThreadedNotifier` and :class:`pyinotify.WatchManager` objects are created.""" Pseudo.start(self) self.watchmgr = pyinotify.WatchManager() self.notifier = pyinotify.ThreadedNotifier(self.watchmgr, self) self.notifier.start() for monitor in self.add_q: self.AddMonitor(*monitor) self.add_q = []
def AddMonitor(self, path, obj, handleID=None): # strip trailing slashes path = path.rstrip("/") if not self.started: self.add_q.append((path, obj)) return path if not os.path.isdir(path): # inotify is a little wonky about watching files. for # instance, if you watch /tmp/foo, and then do 'mv # /tmp/bar /tmp/foo', it processes that as a deletion of # /tmp/foo (which it technically _is_, but that's rather # useless -- we care that /tmp/foo changed, not that it # was first deleted and then created). In order to # effectively watch a file, we have to watch the directory # it's in, and filter out events for other files in the # same directory that are not similarly watched. # watch_transient_file requires a Processor _class_, not # an object, so we can't have this object handle events, # which is Wrong, so we can't use that function. watch_path = os.path.dirname(path) is_dir = False else: watch_path = path is_dir = True # see if this path is already being watched try: watchdir = self.watches_by_path[watch_path] except KeyError: if not os.path.exists(watch_path): raise OSError(errno.ENOENT, "No such file or directory: '%s'" % path) watchdir = self.watchmgr.add_watch(watch_path, self.mask, quiet=False)[watch_path] self.watches_by_path[watch_path] = watchdir produce_exists = True if not is_dir: if watchdir not in self.event_filter: self.event_filter[watchdir] = [path] elif path not in self.event_filter[watchdir]: self.event_filter[watchdir].append(path) else: # we've been asked to watch a file that we're already # watching, so we don't need to produce 'exists' # events produce_exists = False # inotify doesn't produce initial 'exists' events, so we # inherit from Pseudo to produce those if produce_exists: return Pseudo.AddMonitor(self, path, obj, handleID=path) else: self.handles[path] = obj return path
def __init__(self, ignore=None, debug=False): Pseudo.__init__(self, ignore=ignore, debug=debug) pyinotify.ProcessEvent.__init__(self) #: inotify can't set useful monitors directly on files, only #: on directories, so when a monitor is added on a file we add #: its parent directory to ``event_filter`` and then only #: produce events on a file in that directory if the file is #: listed in ``event_filter``. Keys are directories -- the #: parent directories of individual files that are monitored #: -- and values are lists of full paths to files in each #: directory that events *should* be produced for. An event #: on a file whose parent directory is in ``event_filter`` but #: which is not itself listed will be silently suppressed. self.event_filter = dict() #: inotify doesn't like monitoring a path twice, so we keep a #: dict of :class:`pyinotify.Watch` objects, keyed by monitor #: path, to avoid trying to create duplicate monitors. #: (Duplicates can happen if an object accidentally requests #: duplicate monitors, or if two files in a single directory #: are both individually monitored, since inotify can't set #: monitors on the files but only on the parent directories.) self.watches_by_path = dict() #: The :class:`pyinotify.ThreadedNotifier` object. This is #: created in :func:`start` after the server is done #: daemonizing. self.notifier = None #: The :class:`pyinotify.WatchManager` object. This is created #: in :func:`start` after the server is done daemonizing. self.watchmgr = None #: The queue used to record monitors that are added before #: :func:`start` has been called and :attr:`notifier` and #: :attr:`watchmgr` are created. self.add_q = []
def AddMonitor(self, path, obj): res = self.wm.add_watch(path, self.mask, quiet=False) if not res: # if we didn't get a return, but we also didn't get an # exception, we're already watching this directory, so we # need to find the watch descriptor for it for wd, watch in self.wm.watches.items(): if watch.path == path: wd = watch.wd else: wd = res[path] # inotify doesn't produce initial 'exists' events, so we # inherit from Pseudo to produce those return Pseudo.AddMonitor(self, path, obj, handleID=wd)
def shutdown(self): if self.started and self.notifier: self.notifier.stop() Pseudo.shutdown(self)
def __init__(self, ignore=None, debug=False): Pseudo.__init__(self, ignore=ignore, debug=debug) self.wm = pyinotify.WatchManager() self.notifier = pyinotify.ThreadedNotifier(self.wm, self) self.notifier.start()