Beispiel #1
0
def watcher(loop):
    global pathy
    inotify = Inotify_async(loop=loop)
    print(inotify)
    wd = inotify.watch('/home/alathrem/PycharmProjects/TriviaSearch/Imgs',
                       IN_ALL_EVENTS)

    for i in range(1):
        event = yield from inotify.get_event()
        print(event)

    inotify.ignore(wd)
    print('done')

    event = yield from inotify.get_event()
    print(event)
    pathy = (str(event).split(',')[3].split("'")[1])

    inotify.close()
    print(inotify)
Beispiel #2
0
class SyncedRootDirectory(SyncedCachedRootDir):
    """
    A root directory object that can keep itself in sync with the filesystem.
    """
    DirectoryClass = SyncedDirectory

    def __init__(self, path, loop):
        super().__init__(path)
        self._inotify = Inotify_async(loop=loop)
        self._inotifyHandles = {}
        self._inotifyRegister(self)
        self._futureInotifyEvent = None

    def isSynced(self):
        """
        Returns True if the root directory object is completely in sync with the
        filesystem. Does an exhaustive search, and raises a RuntimeError if
        any files are not in sync.

        Because this is an exhaustive search that does not modify any data
        structures, this method is very slow compared to just calling
        ``refresh(recursive=True)``.

        This is primarily intended as a way to validate that the inotify events
        are being processed correctly.
        """
        allFiles = set()
        for item in self.all(recursive=True):
            allFiles.add(item.relpath)

        mirrorFiles = set()
        for item in RootDirectory(self.path).all(recursive=True):
            mirrorFiles.add(item.relpath)
            if item.relpath not in allFiles:
                raise RuntimeError("'%s' not in synced fs" % item.relpath)
                return False

        for item in allFiles:
            if item not in mirrorFiles:
                raise RuntimeError("'%s' in syncedFS but does not exist" %
                                   item.relpath)
                return False

        return True

    def _inotifyRegister(self, dirobj):
        """
        Because the butter library does not do any sort of recursive watching,
        this callback, which is called in the constructor of every directory
        object, will set up a watch for that directory.
        """
        handle = self._inotify.watch(dirobj.abspath, DIR_FLAGS)

        # allow lookups by either handle or relative path
        self._inotifyHandles[handle] = dirobj
        self._inotifyHandles[dirobj.relpath] = handle

    def _getInotifyEventDir(self, evt):
        """
        Takes an inotify event (the butter library object) and returns the inotify
        handle for it.
        """
        return self._inotifyHandles[evt.wd]

    @asyncio.coroutine
    def processFilesystemEvents(self):
        """
        Tries to get new events from the filesystem. If any events exist, more events will be
        retrieved with a timeout of 0.05 seconds until the timeout expires, at which time
        all of the retrieved events will be processed.

        Each event will be processed so that this object stays in sync with the filesystem.

        A list of all processed events will be returned in a list of ``FileEvent`` objects,
        which is a namedtuple containing 3 fields: ``type``, ``parent``, ``name``.

        | ``type`` is a string which will contain one of the following values: "create",
        | "modify", "delete", "movefrom", "moveto"
        |
        | ``parent`` is a directory object that is the parent directory of the file or
        | directory that the event refers to.
        |
        | ``name`` is the name of the file or directory that the event refers to.

        Note that in the returned list of events, any time a "movefrom" event occurs, a
        "moveto" event is guaranteed to come after it.
        """
        if self._futureInotifyEvent is None:
            self._futureInotifyEvent = asyncio.ensure_future(
                self._inotify.get_event())

        results = []
        if self._futureInotifyEvent is not None and self._futureInotifyEvent.done(
        ):
            try:
                result = self._futureInotifyEvent.result()
                results.append(result)
            except asyncio.CancelledError:
                return []

            # see if more events will follow this one
            moreEvents = True
            while moreEvents:
                try:
                    nextResult = yield from asyncio.wait_for(
                        self._inotify.get_event(), 0.05)
                    results.append(nextResult)
                except asyncio.TimeoutError:
                    moreEvents = False

            self._futureInotifyEvent = None

        # for every event, we're going to add a 3-tuple to this array representing the event
        returnValues = []

        # go through all the results and route them to helper methods on the Directory objects
        for i in range(len(results)):
            dirobj = None

            evt = results[i]

            # nextEvt is the event object following this one. we need this because
            # movefrom and moveto are different events and we need them as a pair
            if i < len(results) - 1:
                nextEvt = results[i + 1]
            else:
                nextEvt = None

            # is this a directory event?
            isDir = False
            if evt.is_dir_event:
                isDir = True

            # get the directory object we're going to route the event to
            dirobj = self._getInotifyEventDir(evt)

            # a file or directory was created
            if evt.create_event:
                dirobj._inotifyCreate(evt, isDir)
                returnValues.append(
                    FileEvent("create", dirobj, evt.filename.decode()))

            # a file or directory was modified
            elif evt.modify_event:
                dirobj._inotifyModify(evt, isDir)
                returnValues.append(
                    FileEvent("modify", dirobj, evt.filename.decode()))

            # a file or directory was deleted
            elif evt.delete_event:
                dirobj._inotifyDelete(evt, isDir)
                returnValues.append(
                    FileEvent("delete", dirobj, evt.filename.decode()))

            # a file or directory was moved
            elif nextEvt is not None and (evt.moved_from_event
                                          or evt.moved_to_event):
                # we need to figure out the order. one event is movefrom and one event is moveto.
                evtFrom = None
                evtTo = None

                if evt.moved_from_event:
                    evtFrom = evt
                elif evt.moved_to_event:
                    evtTo = evt

                if nextEvt.moved_from_event:
                    evtFrom = nextEvt
                elif nextEvt.moved_to_event:
                    evtTo = nextEvt

                # make sure we actually get a movefrom/moveto pair
                if evtFrom is not None and evtTo is not None:
                    nextDirobj = self._getInotifyEventDir(nextEvt)
                    dirobj._inotifyMove(evt, nextEvt, nextDirobj, isDir)
                    # in our return values, movefrom and moveto will ALWAYS be a pair, and
                    # movefrom will ALWAYS come before moveto.
                    returnValues.append(
                        FileEvent("movefrom", dirobj,
                                  evtFrom.filename.decode()))
                    returnValues.append(
                        FileEvent("moveto", nextDirobj,
                                  evtTo.filename.decode()))

                # didn't get a pair, log an error
                else:
                    filename = os.path.join(dirobj.abspath,
                                            evt.filename.decode())
                    logging.error(
                        "Expected a MOVED_FROM and MOVED_TO pair, got %s and %s for file '%s'"
                        % (_flagsToStr(evt), _flagsToStr(nextEvt), filename))

        return returnValues
Beispiel #3
0
class SyncedRootDirectory(SyncedCachedRootDir):
    """
    A root directory object that can keep itself in sync with the filesystem.
    """
    DirectoryClass = SyncedDirectory


    def __init__(self, path, loop):
        super().__init__(path)
        self._inotify = Inotify_async(loop=loop)
        self._inotifyHandles = {}
        self._inotifyRegister(self)
        self._futureInotifyEvent = None


    def isSynced(self):
        """
        Returns True if the root directory object is completely in sync with the
        filesystem. Does an exhaustive search, and raises a RuntimeError if
        any files are not in sync.

        Because this is an exhaustive search that does not modify any data
        structures, this method is very slow compared to just calling
        ``refresh(recursive=True)``.

        This is primarily intended as a way to validate that the inotify events
        are being processed correctly.
        """
        allFiles = set()
        for item in self.all(recursive=True):
            allFiles.add(item.relpath)

        mirrorFiles = set()
        for item in RootDirectory(self.path).all(recursive=True):
            mirrorFiles.add(item.relpath)
            if item.relpath not in allFiles:
                raise RuntimeError("'%s' not in synced fs" % item.relpath)
                return False

        for item in allFiles:
            if item not in mirrorFiles:
                raise RuntimeError("'%s' in syncedFS but does not exist" % item.relpath)
                return False

        return True


    def _inotifyRegister(self, dirobj):
        """
        Because the butter library does not do any sort of recursive watching,
        this callback, which is called in the constructor of every directory
        object, will set up a watch for that directory.
        """
        handle = self._inotify.watch(dirobj.abspath, DIR_FLAGS)

        # allow lookups by either handle or relative path
        self._inotifyHandles[handle] = dirobj
        self._inotifyHandles[dirobj.relpath] = handle


    def _getInotifyEventDir(self, evt):
        """
        Takes an inotify event (the butter library object) and returns the inotify
        handle for it.
        """
        return self._inotifyHandles[evt.wd]


    @asyncio.coroutine
    def processFilesystemEvents(self):
        """
        Tries to get new events from the filesystem. If any events exist, more events will be
        retrieved with a timeout of 0.05 seconds until the timeout expires, at which time
        all of the retrieved events will be processed.

        Each event will be processed so that this object stays in sync with the filesystem.

        A list of all processed events will be returned in a list of ``FileEvent`` objects,
        which is a namedtuple containing 3 fields: ``type``, ``parent``, ``name``.

        | ``type`` is a string which will contain one of the following values: "create",
        | "modify", "delete", "movefrom", "moveto"
        | 
        | ``parent`` is a directory object that is the parent directory of the file or
        | directory that the event refers to.
        |
        | ``name`` is the name of the file or directory that the event refers to.

        Note that in the returned list of events, any time a "movefrom" event occurs, a
        "moveto" event is guaranteed to come after it.
        """
        if self._futureInotifyEvent is None:
            self._futureInotifyEvent = asyncio.ensure_future(self._inotify.get_event())

        results = []
        if self._futureInotifyEvent is not None and self._futureInotifyEvent.done():
            try:
                result = self._futureInotifyEvent.result()
                results.append(result)
            except asyncio.CancelledError:
                return []

            # see if more events will follow this one
            moreEvents = True
            while moreEvents:
                try:
                    nextResult = yield from asyncio.wait_for(self._inotify.get_event(), 0.05)
                    results.append(nextResult)
                except asyncio.TimeoutError:
                    moreEvents = False

            self._futureInotifyEvent = None

        # for every event, we're going to add a 3-tuple to this array representing the event
        returnValues = []

        # go through all the results and route them to helper methods on the Directory objects
        for i in range(len(results)):
            dirobj = None

            evt = results[i]

            # nextEvt is the event object following this one. we need this because
            # movefrom and moveto are different events and we need them as a pair
            if i < len(results) - 1:
                nextEvt = results[i + 1]
            else:
                nextEvt = None

            # is this a directory event?
            isDir = False
            if evt.is_dir_event:
                isDir = True

            # get the directory object we're going to route the event to
            dirobj = self._getInotifyEventDir(evt)

            # a file or directory was created
            if evt.create_event:
                dirobj._inotifyCreate(evt, isDir)
                returnValues.append(FileEvent("create", dirobj, evt.filename.decode()))

            # a file or directory was modified
            elif evt.modify_event:
                dirobj._inotifyModify(evt, isDir)
                returnValues.append(FileEvent("modify", dirobj, evt.filename.decode()))

            # a file or directory was deleted
            elif evt.delete_event:
                dirobj._inotifyDelete(evt, isDir)
                returnValues.append(FileEvent("delete", dirobj, evt.filename.decode()))

            # a file or directory was moved
            elif nextEvt is not None and (evt.moved_from_event or evt.moved_to_event):
                # we need to figure out the order. one event is movefrom and one event is moveto.
                evtFrom = None
                evtTo = None

                if evt.moved_from_event:
                    evtFrom = evt
                elif evt.moved_to_event:
                    evtTo = evt

                if nextEvt.moved_from_event:
                    evtFrom = nextEvt
                elif nextEvt.moved_to_event:
                    evtTo = nextEvt

                # make sure we actually get a movefrom/moveto pair
                if evtFrom is not None and evtTo is not None:
                    nextDirobj = self._getInotifyEventDir(nextEvt)
                    dirobj._inotifyMove(evt, nextEvt, nextDirobj, isDir)
                    # in our return values, movefrom and moveto will ALWAYS be a pair, and
                    # movefrom will ALWAYS come before moveto.
                    returnValues.append(FileEvent("movefrom", dirobj, evtFrom.filename.decode()))
                    returnValues.append(FileEvent("moveto", nextDirobj, evtTo.filename.decode()))

                # didn't get a pair, log an error
                else:
                    filename = os.path.join(dirobj.abspath, evt.filename.decode())
                    logging.error("Expected a MOVED_FROM and MOVED_TO pair, got %s and %s for file '%s'" % (
                        _flagsToStr(evt), _flagsToStr(nextEvt), filename))

        return returnValues