def directoryChangedEvent(self, childName): if childName: # If we're observing a folder and something changes (deep) # inside of it, notify. # TODO: keep a childrenByName dict so we won't have to loop for child in self.children.values(): if child.name == childName: childPath = os.path.join(self.path, child.name) child.callCallbacks(childPath, childPath, True) break return inodes = {} # gather the inodes that _may_ have changed for name in os.listdir(self.path): childPath = os.path.join(self.path, name) st = os.stat(childPath) if st.st_ino in self.children: inodes[st.st_ino] = (name, st.st_mtime) # add inodes for files/folders that were no longer found for inode in set(self.children) - set(inodes): # This one moved away inodes[inode] = (self.children[inode].name, None) movedOrDeleted = [] for inode, (name, modTime) in inodes.items(): child = self.children[inode] oldPath = os.path.join(self.path, child.name) if modTime is None: # This file or folder moved somewhere else or got deleted. Let's find out # by resolving our bookmark data url, isStale, error = NSURL.URLByResolvingBookmarkData_options_relativeToURL_bookmarkDataIsStale_error_( child.bookmarkData, 0, None, None, None) if url is None: # file was deleted newPath = None child.name = None wasModified = False else: # TODO: Check whether it was moved to the trash, and treat special # os.listdir() will fail on a Trash folder newPath = url.path() child.name = os.path.basename(newPath) # update name bookmarkData, error = url.bookmarkDataWithOptions_includingResourceValuesForKeys_relativeToURL_error_( 0, None, None, None) assert error is None, error child.bookmarkData = bookmarkData wasModified = child.modTime != os.stat(newPath).st_mtime wasRenamed = True movedOrDeleted.append((inode, child, newPath)) else: wasModified = child.modTime != modTime if wasModified: child.modTime = modTime wasRenamed = child.name != name if wasRenamed: child.name = name newPath = os.path.join(self.path, name) else: newPath = oldPath if wasRenamed or wasModified: child.callCallbacks(oldPath, newPath, wasModified) for inode, child, newPath in movedOrDeleted: del self.children[inode] return movedOrDeleted