def process_events(self, action, file_name, cookie, syncdaemon_path): """Process the events from the queue.""" # do not process events when the watch was stopped if not self.platform_watch.watching: return # do not process those events that should be ignored if any([file_name.startswith(path) for path in self.ignore_paths]): return # map the filesystem events to the pyinotify ones, tis is dirty but # makes the multiplatform better, linux was first :P full_dir_path = os.path.join(self.path, file_name) is_dir = self._path_is_dir(full_dir_path) if is_dir: # we need to update the list of subdirs that we have self._update_subdirs(full_dir_path, action) mask = ACTIONS[action] head, tail = os.path.split(file_name) if is_dir: mask |= IN_ISDIR event_raw_data = { 'wd': self._descriptor, 'dir': is_dir, 'mask': mask, 'name': tail, 'path': '.'} # by the way in which the api fires the events we know for # sure that no move events will be added in the wrong order, this # is kind of hacky, I dont like it too much if ACTIONS[action] == IN_MOVED_FROM: self._cookie = cookie self._source_pathname = tail event_raw_data['cookie'] = self._cookie if ACTIONS[action] == IN_MOVED_TO: event_raw_data['src_pathname'] = self._source_pathname event_raw_data['cookie'] = self._cookie event = Event(event_raw_data) # FIXME: event deduces the pathname wrong and we need to manually # set it event.pathname = syncdaemon_path # add the event only if we do not have an exclude filter or # the exclude filter returns False, that is, the event will not # be excluded self.log.debug('Pushing event %r to processor.', event) self._processor(event)
def generate_from_event(self, event, cookie): """Return a fake from event from a rename one.""" source_path = get_syncdaemon_valid_path(event.event_paths[0]) mask = IN_MOVED_FROM if event.is_directory: mask |= IN_ISDIR head, tail = os.path.split(source_path) event_raw_data = { 'wd': 0, # we only have one factory 'dir': event.is_directory, 'mask': mask, 'name': tail, 'cookie': cookie, 'path': '.'} move_from_event = Event(event_raw_data) move_from_event.pathname = source_path return move_from_event
def process_IN_MODIFY(self, event): """Capture a modify event and fake an open ^ close write events.""" # lets ignore dir changes if event.dir: return # on someplatforms we just get IN_MODIFY, lets always fake # an OPEN & CLOSE_WRITE couple raw_open = raw_close = { 'wd': event.wd, 'dir': event.dir, 'name': event.name, 'path': event.path} # caculate the open mask raw_open['mask'] = IN_OPEN # create the event using the raw data, then fix the pathname param open_event = Event(raw_open) open_event.pathname = event.pathname # push the open self.general_processor.push_event(open_event) raw_close['mask'] = IN_CLOSE_WRITE close_event = Event(raw_close) close_event.pathname = event.pathname # push the close event self.general_processor.push_event(close_event)
def convert_in_pyinotify_event(self, event): """Get an event from the daemon and convert it in a pyinotify one.""" # the rename is a special type of event because it has to be either # converted is a pair of events or in a single one (CREATE or DELETE) if event.event_type == fseventsd.FSE_RENAME: is_create = self.is_create(event) is_delete = self.is_delete(event) if is_create or is_delete: mask = IN_CREATE if is_create else IN_DELETE if event.is_directory: mask |= IN_ISDIR # a create means that we moved from a not watched path to a # watched one and therefore we are interested in the SECOND # path of the event. A delete means that we moved from a # watched path for a not watched one and we care about the # FIRST path of the event path = ( event.event_paths[1] if is_create else event.event_paths[0] ) path = get_syncdaemon_valid_path(path) head, tail = os.path.split(path) event_raw_data = { 'wd': 0, # we only have one factory 'dir': event.is_directory, 'mask': mask, 'name': tail, 'path': '.'} orig_event = Event(event_raw_data) orig_event.pathname = path events = [orig_event] if is_create: mod_event = Event(event_raw_data) mod_event.pathname = path mod_event.mask = IN_MODIFY if event.is_directory: mod_event.mask |= IN_ISDIR events.append(mod_event) return events else: # we have a rename within watched paths, so let's # generate two fake events cookie = str(uuid4()) return [self.generate_from_event(event, cookie), self.generate_to_event(event, cookie)] else: mask = DARWIN_ACTIONS[event.event_type] if event.is_directory: mask |= IN_ISDIR # we do know that we are not dealing with a move which are the only # events that have more than one path path = get_syncdaemon_valid_path(event.event_paths[0]) head, tail = os.path.split(path) event_raw_data = { 'wd': 0, # we only have one factory 'dir': event.is_directory, 'mask': mask, 'name': tail, 'path': '.'} pyinotify_event = Event(event_raw_data) # FIXME: event deduces the pathname wrong and we need to manually # set it pyinotify_event.pathname = path return [pyinotify_event]