def test_sub_moved_events(self):
        mock_walker_path = [
            ('/path', ['ad', 'bd'], ['af', 'bf', 'cf']),
            ('/path/ad', [], ['af', 'bf', 'cf']),
            ('/path/bd', [], ['af', 'bf', 'cf']),
        ]
        dest_path = '/path'
        src_path = '/foobar'
        expected_events = set([
            DirMovedEvent('/foobar/ad', '/path/ad'),
            DirMovedEvent('/foobar/bd', '/path/bd'),
            FileMovedEvent('/foobar/af', '/path/af'),
            FileMovedEvent('/foobar/bf', '/path/bf'),
            FileMovedEvent('/foobar/cf', '/path/cf'),
            FileMovedEvent('/foobar/ad/af', '/path/ad/af'),
            FileMovedEvent('/foobar/ad/bf', '/path/ad/bf'),
            FileMovedEvent('/foobar/ad/cf', '/path/ad/cf'),
            FileMovedEvent('/foobar/bd/af', '/path/bd/af'),
            FileMovedEvent('/foobar/bd/bf', '/path/bd/bf'),
            FileMovedEvent('/foobar/bd/cf', '/path/bd/cf'),
        ])
        dir_moved_event = DirMovedEvent(src_path, dest_path)

        def _mock_os_walker(path):
            for root, directories, filenames in mock_walker_path:
                yield (root, directories, filenames)

        calculated_events = set(
            dir_moved_event.sub_moved_events(_walker=_mock_os_walker))
        assert_equal(expected_events, calculated_events)
Exemple #2
0
    def _queue_renamed(self, src_path, is_directory, ref_snapshot,
                       new_snapshot):
        try:
            ref_stat_info = ref_snapshot.stat_info(src_path)
        except KeyError:
            if is_directory:
                self.queue_event(DirCreatedEvent(src_path))
                self.queue_event(DirDeletedEvent(src_path))
            else:
                self.queue_event(FileCreatedEvent(src_path))
                self.queue_event(FileDeletedEvent(src_path))
            return

        try:
            dest_path = absolute_path(
                new_snapshot.path_for_inode(ref_stat_info.st_ino))
            if is_directory:
                event = DirMovedEvent(src_path, dest_path)
                if self.watch.is_recursive:
                    for sub_event in event.sub_moved_events():
                        self.queue_event(sub_event)

                self.queue_event(event)
            else:
                self.queue_event(FileMovedEvent(src_path, dest_path))
        except KeyError:
            if is_directory:
                self.queue_event(DirDeletedEvent(src_path))
            else:
                self.queue_event(FileDeletedEvent(src_path))
Exemple #3
0
    def queue_events(self, timeout):
        with self._lock:
            dir_changes, nbytes = read_directory_changes(self._directory_handle, self._buffer, self.watch.is_recursive)
            last_renamed_src_path = ''
            for action, src_path in get_FILE_NOTIFY_INFORMATION(dir_changes, nbytes):
                src_path = absolute_path(os.path.join(self.watch.path, src_path))
                if action == FILE_ACTION_RENAMED_OLD_NAME:
                    last_renamed_src_path = src_path
                elif action == FILE_ACTION_RENAMED_NEW_NAME:
                    dest_path = src_path
                    src_path = last_renamed_src_path
                    if os.path.isdir(dest_path):
                        event = DirMovedEvent(src_path, dest_path)
                        if self.watch.is_recursive:
                            time.sleep(WATCHDOG_TRAVERSE_MOVED_DIR_DELAY)
                            for sub_moved_event in event.sub_moved_events():
                                self.queue_event(sub_moved_event)

                        self.queue_event(event)
                    else:
                        self.queue_event(FileMovedEvent(src_path, dest_path))
                elif os.path.isdir(src_path):
                    event = DIR_ACTION_EVENT_MAP[action](src_path)
                    if isinstance(event, DirCreatedEvent):
                        time.sleep(WATCHDOG_TRAVERSE_MOVED_DIR_DELAY)
                        sub_events = _generate_sub_created_events_for(src_path)
                        for sub_created_event in sub_events:
                            self.queue_event(sub_created_event)

                    self.queue_event(event)
                else:
                    self.queue_event(FILE_ACTION_EVENT_MAP[action](src_path))
    def _queue_renamed(self, src_path, is_directory, ref_snapshot, new_snapshot):
        try:
            ref_stat_info = ref_snapshot.stat_info(src_path)
        except KeyError:
            if is_directory:
                self.queue_event(DirCreatedEvent(src_path))
                self.queue_event(DirDeletedEvent(src_path))
            else:
                self.queue_event(FileCreatedEvent(src_path))
                self.queue_event(FileDeletedEvent(src_path))
            return

        try:
            dest_path = absolute_path(new_snapshot.path_for_inode(ref_stat_info.st_ino))
            if is_directory:
                event = DirMovedEvent(src_path, dest_path)
                if self.watch.is_recursive:
                    for sub_event in event.sub_moved_events():
                        self.queue_event(sub_event)

                self.queue_event(event)
            else:
                self.queue_event(FileMovedEvent(src_path, dest_path))
        except KeyError:
            if is_directory:
                self.queue_event(DirDeletedEvent(src_path))
            else:
                self.queue_event(FileDeletedEvent(src_path))
    def test_sub_moved_events(self):
        mock_walker_path = [
            ('/path',
                ['ad', 'bd'],
                ['af', 'bf', 'cf']),
            ('/path/ad',
                [],
                ['af', 'bf', 'cf']),
            ('/path/bd',
                [],
                ['af', 'bf', 'cf']),
        ]
        dest_path = '/path'
        src_path = '/foobar'
        expected_events = set([
            DirMovedEvent('/foobar/ad', '/path/ad'),
            DirMovedEvent('/foobar/bd', '/path/bd'),
            FileMovedEvent('/foobar/af', '/path/af'),
            FileMovedEvent('/foobar/bf', '/path/bf'),
            FileMovedEvent('/foobar/cf', '/path/cf'),
            FileMovedEvent('/foobar/ad/af', '/path/ad/af'),
            FileMovedEvent('/foobar/ad/bf', '/path/ad/bf'),
            FileMovedEvent('/foobar/ad/cf', '/path/ad/cf'),
            FileMovedEvent('/foobar/bd/af', '/path/bd/af'),
            FileMovedEvent('/foobar/bd/bf', '/path/bd/bf'),
            FileMovedEvent('/foobar/bd/cf', '/path/bd/cf'),
        ])
        dir_moved_event = DirMovedEvent(src_path, dest_path)

        def _mock_os_walker(path):
            for root, directories, filenames in mock_walker_path:
                yield (root, directories, filenames)
        calculated_events = set(dir_moved_event.sub_moved_events(_walker=_mock_os_walker))
        assert_equal(expected_events, calculated_events)
        def queue_events(self, timeout):
            with self._lock:
                dir_changes, nbytes = read_directory_changes(
                    self._directory_handle, self._buffer,
                    self.watch.is_recursive)
                last_renamed_src_path = ""
                for action, src_path in get_FILE_NOTIFY_INFORMATION(
                        dir_changes, nbytes):
                    src_path = absolute_path(
                        os.path.join(self.watch.path, src_path))

                    if action == FILE_ACTION_RENAMED_OLD_NAME:
                        last_renamed_src_path = src_path
                    elif action == FILE_ACTION_RENAMED_NEW_NAME:
                        dest_path = src_path
                        src_path = last_renamed_src_path

                        if os.path.isdir(dest_path):
                            event = DirMovedEvent(src_path, dest_path)
                            if self.watch.is_recursive:
                                # HACK: We introduce a forced delay before
                                # traversing the moved directory. This will read
                                # only file movement that finishes within this
                                # delay time.
                                time.sleep(WATCHDOG_TRAVERSE_MOVED_DIR_DELAY)
                                # The following block of code may not
                                # obtain moved events for the entire tree if
                                # the I/O is not completed within the above
                                # delay time. So, it's not guaranteed to work.
                                # TODO: Come up with a better solution, possibly
                                # a way to wait for I/O to complete before
                                # queuing events.
                                for sub_moved_event in event.sub_moved_events(
                                ):
                                    self.queue_event(sub_moved_event)
                            self.queue_event(event)
                        else:
                            self.queue_event(
                                FileMovedEvent(src_path, dest_path))
                    else:
                        if os.path.isdir(src_path):
                            event = DIR_ACTION_EVENT_MAP[action](src_path)
                            if isinstance(event, DirCreatedEvent):
                                # If a directory is moved from outside the watched folder to inside it
                                # we only get a created directory event out of it, not any events for its children
                                # so use the same hack as for file moves to get the child events
                                time.sleep(WATCHDOG_TRAVERSE_MOVED_DIR_DELAY)
                                sub_events = _generate_sub_created_events_for(
                                    src_path)
                                for sub_created_event in sub_events:
                                    self.queue_event(sub_created_event)
                            self.queue_event(event)
                        else:
                            self.queue_event(
                                FILE_ACTION_EVENT_MAP[action](src_path))
    def queue_events(self, timeout):
      with self._lock:
        dir_changes, nbytes = read_directory_changes(self._directory_handle,
                                                     self._buffer,
                                                     self.watch.is_recursive)
        last_renamed_src_path = ""
        for action, src_path in get_FILE_NOTIFY_INFORMATION(dir_changes,
                                                            nbytes):
          src_path = absolute_path(os.path.join(self.watch.path,
                                                src_path))

          if action == FILE_ACTION_RENAMED_OLD_NAME:
            continue
            last_renamed_src_path = src_path
          elif action == FILE_ACTION_RENAMED_NEW_NAME:
            continue
            dest_path = src_path
            src_path = last_renamed_src_path

            if os.path.isdir(dest_path):
              event = DirMovedEvent(src_path, dest_path)
              if self.watch.is_recursive:
                # HACK: We introduce a forced delay before
                # traversing the moved directory. This will read
                # only file movement that finishes within this
                # delay time.
                time.sleep(WATCHDOG_TRAVERSE_MOVED_DIR_DELAY)
                # The following block of code may not
                # obtain moved events for the entire tree if
                # the I/O is not completed within the above
                # delay time. So, it's not guaranteed to work.
                # TODO: Come up with a better solution, possibly
                # a way to wait for I/O to complete before
                # queuing events.
                for sub_moved_event in event.sub_moved_events():
                  self.queue_event(sub_moved_event)
              self.queue_event(event)
            else:
              self.queue_event(FileMovedEvent(src_path, dest_path))
          else:
            if os.path.isdir(src_path):
              continue
              event = DIR_ACTION_EVENT_MAP[action](src_path)
              if isinstance(event, DirCreatedEvent):
                # If a directory is moved from outside the watched folder to inside it
                # we only get a created directory event out of it, not any events for its children
                # so use the same hack as for file moves to get the child events
                time.sleep(WATCHDOG_TRAVERSE_MOVED_DIR_DELAY)
                sub_events = _generate_sub_created_events_for(src_path)
                for sub_created_event in sub_events:
                  self.queue_event(sub_created_event)
              self.queue_event(event)
            else:
              self.queue_event(FILE_ACTION_EVENT_MAP[action](src_path))
Exemple #8
0
    def _queue_renamed(self,
                       src_path,
                       is_directory,
                       ref_snapshot,
                       new_snapshot):
        """
        Compares information from two directory snapshots (one taken before
        the rename operation and another taken right after) to determine the
        destination path of the file system object renamed, and adds
        appropriate events to the event queue.
        """
        try:
            ref_stat_info = ref_snapshot.stat_info(src_path)
        except KeyError:
            # Probably caught a temporary file/directory that was renamed
            # and deleted. Fires a sequence of created and deleted events
            # for the path.
            if is_directory:
                self.queue_event(DirCreatedEvent(src_path))
                self.queue_event(DirDeletedEvent(src_path))
            else:
                self.queue_event(FileCreatedEvent(src_path))
                self.queue_event(FileDeletedEvent(src_path))
                # We don't process any further and bail out assuming
            # the event represents deletion/creation instead of movement.
            return

        try:
            dest_path = absolute_path(
                new_snapshot.path_for_inode(ref_stat_info.st_ino))
            if is_directory:
                event = DirMovedEvent(src_path, dest_path)
                # TODO: Do we need to fire moved events for the items
                # inside the directory tree? Does kqueue does this
                # all by itself? Check this and then enable this code
                # only if it doesn't already.
                # A: It doesn't. So I've enabled this block.
                if self.watch.is_recursive:
                    for sub_event in event.sub_moved_events():
                        self.queue_event(sub_event)
                self.queue_event(event)
            else:
                self.queue_event(FileMovedEvent(src_path, dest_path))
        except KeyError:
            # If the new snapshot does not have an inode for the
            # old path, we haven't found the new name. Therefore,
            # we mark it as deleted and remove unregister the path.
            if is_directory:
                self.queue_event(DirDeletedEvent(src_path))
            else:
                self.queue_event(FileDeletedEvent(src_path))
Exemple #9
0
    def _queue_renamed(self,
                       src_path,
                       is_directory,
                       ref_snapshot,
                       new_snapshot):
        """
        Compares information from two directory snapshots (one taken before
        the rename operation and another taken right after) to determine the
        destination path of the file system object renamed, and adds
        appropriate events to the event queue.
        """
        try:
            ref_stat_info = ref_snapshot.stat_info(src_path)
        except KeyError:
            # Probably caught a temporary file/directory that was renamed
            # and deleted. Fires a sequence of created and deleted events
            # for the path.
            if is_directory:
                self.queue_event(DirCreatedEvent(src_path))
                self.queue_event(DirDeletedEvent(src_path))
            else:
                self.queue_event(FileCreatedEvent(src_path))
                self.queue_event(FileDeletedEvent(src_path))
                # We don't process any further and bail out assuming
            # the event represents deletion/creation instead of movement.
            return

        try:
            dest_path = absolute_path(
                new_snapshot.path(ref_stat_info.st_ino))
            if is_directory:
                event = DirMovedEvent(src_path, dest_path)
                # TODO: Do we need to fire moved events for the items
                # inside the directory tree? Does kqueue does this
                # all by itself? Check this and then enable this code
                # only if it doesn't already.
                # A: It doesn't. So I've enabled this block.
                if self.watch.is_recursive:
                    for sub_event in event.sub_moved_events():
                        self.queue_event(sub_event)
                self.queue_event(event)
            else:
                self.queue_event(FileMovedEvent(src_path, dest_path))
        except KeyError:
            # If the new snapshot does not have an inode for the
            # old path, we haven't found the new name. Therefore,
            # we mark it as deleted and remove unregister the path.
            if is_directory:
                self.queue_event(DirDeletedEvent(src_path))
            else:
                self.queue_event(FileDeletedEvent(src_path))
Exemple #10
0
        def queue_events(self, timeout):
            with self._lock:
                dir_changes, nbytes = read_directory_changes(
                    self._directory_handle, self._buffer,
                    self.watch.is_recursive)
                last_renamed_src_path = ""
                for action, src_path in get_FILE_NOTIFY_INFORMATION(
                        dir_changes, nbytes):
                    src_path = absolute_path(
                        os.path.join(self.watch.path, src_path))

                    if action == FILE_ACTION_RENAMED_OLD_NAME:
                        last_renamed_src_path = src_path
                    elif action == FILE_ACTION_RENAMED_NEW_NAME:
                        dest_path = src_path
                        src_path = last_renamed_src_path

                        if os.path.isdir(src_path):
                            event = DirMovedEvent(src_path, dest_path)
                            if self.watch.is_recursive:
                                # HACK: We introduce a forced delay before
                                # traversing the moved directory. This will read
                                # only file movement that finishes within this
                                # delay time.
                                time.sleep(WATCHDOG_TRAVERSE_MOVED_DIR_DELAY)
                                # The following block of code may not
                                # obtain moved events for the entire tree if
                                # the I/O is not completed within the above
                                # delay time. So, it's not guaranteed to work.
                                # TODO: Come up with a better solution, possibly
                                # a way to wait for I/O to complete before
                                # queuing events.
                                for sub_moved_event in event.sub_moved_events(
                                ):
                                    self.queue_event(sub_moved_event)
                            self.queue_event(event)
                        else:
                            self.queue_event(
                                FileMovedEvent(src_path, dest_path))
                    else:
                        if os.path.isdir(src_path):
                            action_event_map = DIR_ACTION_EVENT_MAP
                        else:
                            action_event_map = FILE_ACTION_EVENT_MAP
                        self.queue_event(action_event_map[action](src_path))
    def queue_events(self, timeout):
      with self._lock:
        dir_changes, nbytes = read_directory_changes(self._directory_handle,
                                                     self._buffer,
                                                     self.watch.is_recursive)
        last_renamed_src_path = ""
        for action, src_path in get_FILE_NOTIFY_INFORMATION(dir_changes,
                                                            nbytes):
          src_path = absolute_path(os.path.join(self.watch.path,
                                                src_path))

          if action == FILE_ACTION_RENAMED_OLD_NAME:
            last_renamed_src_path = src_path
          elif action == FILE_ACTION_RENAMED_NEW_NAME:
            dest_path = src_path
            src_path = last_renamed_src_path

            if os.path.isdir(dest_path):
              event = DirMovedEvent(src_path, dest_path)
              if self.watch.is_recursive:
                # HACK: We introduce a forced delay before
                # traversing the moved directory. This will read
                # only file movement that finishes within this
                # delay time.
                time.sleep(WATCHDOG_TRAVERSE_MOVED_DIR_DELAY)
                # The following block of code may not
                # obtain moved events for the entire tree if
                # the I/O is not completed within the above
                # delay time. So, it's not guaranteed to work.
                # TODO: Come up with a better solution, possibly
                # a way to wait for I/O to complete before
                # queuing events.
                for sub_moved_event in event.sub_moved_events():
                  self.queue_event(sub_moved_event)
              self.queue_event(event)
            else:
              self.queue_event(FileMovedEvent(src_path,
                                              dest_path))
          else:
            if os.path.isdir(src_path):
              action_event_map = DIR_ACTION_EVENT_MAP
            else:
              action_event_map = FILE_ACTION_EVENT_MAP
            self.queue_event(action_event_map[action](src_path))
Exemple #12
0
    def _queue_renamed(self, src_path, is_directory, ref_snapshot,
                       new_snapshot):
        """
        Compares information from two directory snapshots (one taken before
        the rename operation and another taken right after) to determine the
        destination path of the file system object renamed, and adds
        appropriate events to the event queue.
        """
        try:
            ref_stat_info = ref_snapshot.stat_info(src_path)
        except KeyError:
            if is_directory:
                self.queue_event(DirCreatedEvent(src_path))
                self.queue_event(DirDeletedEvent(src_path))
            else:
                self.queue_event(FileCreatedEvent(src_path))
                self.queue_event(FileDeletedEvent(src_path))
            return

        try:
            dest_path = absolute_path(
                new_snapshot.path_for_inode(ref_stat_info.st_ino))
            if is_directory:
                event = DirMovedEvent(src_path, dest_path)
                if self.watch.is_recursive:
                    for sub_event in event.sub_moved_events():
                        self.queue_event(sub_event)

                self.queue_event(event)
            else:
                self.queue_event(FileMovedEvent(src_path, dest_path))
        except KeyError:
            if is_directory:
                self.queue_event(DirDeletedEvent(src_path))
            else:
                self.queue_event(FileDeletedEvent(src_path))