<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def rescan(self):
 """Checks files and directories on watchlist for updates, rescans them for new data products. If any are found, returns them. Skips those in directories whose watchingState is set to Purr.UNWATCHED. """

        if not self.attached:
            return
        dprint(5, "starting rescan")
        newstuff = {};  # this accumulates names of new or changed files. Keys are paths, values are 'quiet' flag.
        # store timestamp of scan
        self.last_scan_timestamp = time.time()
        # go through watched files/directories, check for mtime changes
        for path, watcher in list(self.watchers.items()):
            # get list of new files from watcher
            newfiles = watcher.newFiles()
            # None indicates access error, so drop it from watcher set
            if newfiles is None:
                if watcher.survive_deletion:
                    dprintf(5, "access error on %s, but will still be watched\n", watcher.path)
                else:
                    dprintf(2, "access error on %s, will no longer be watched\n", watcher.path)
                    del self.watchers[path]
                if not watcher.disappeared:
                    self.emit(SIGNAL("disappearedFile"), path)
                    watcher.disappeared = True
                continue
            dprintf(5, "%s: %d new file(s)\n", watcher.path, len(newfiles))
            # if a file has its own watcher, and is independently reported by a directory watcher, skip the directory's
            # version and let the file's watcher report it. Reason for this is that the file watcher may have a more
            # up-to-date timestamp, so we trust it over the dir watcher.
            newfiles = [p for p in newfiles if p is path or p not in self.watchers]
            # skip files in self._unwatched_paths
            newfiles = [filename for filename in newfiles if
                        self._watching_state.get(os.path.dirname(filename)) > Purr.UNWATCHED]
            # Now go through files and add them to the newstuff dict
            for newfile in newfiles:
                # if quiet flag is explicitly set on watcher, enforce it
                # if not pouncing on directory, also add quietly
                if watcher.quiet or self._watching_state.get(os.path.dirname(newfile)) < Purr.POUNCE:
                    quiet = True
                # else add quietly if file is not in the quiet patterns
                else:
                    quiet = matches_patterns(os.path.basename(newfile), self._quiet_patterns)
                # add file to list of new products. Since a file may be reported by multiple
                # watchers, make the quiet flag a logical AND of all the quiet flags (i.e. DP will be
                # marked as quiet only if all watchers report it as quiet).
                newstuff[newfile] = quiet and newstuff.get(newfile, True)
                dprintf(4, "%s: new data product, quiet=%d (watcher quiet: %s)\n", newfile, quiet, watcher.quiet)
                # add a watcher for this file to the temp_watchers list. this is used below
                # to detect renamed and deleted files
                self.temp_watchers[newfile] = Purrer.WatchedFile(newfile)
        # now, go through temp_watchers to see if any newly pounced-on files have disappeared
        for path, watcher in list(self.temp_watchers.items()):
            # get list of new files from watcher
            if watcher.newFiles() is None:
                dprintf(2, "access error on %s, marking as disappeared", watcher.path)
                del self.temp_watchers[path]
                self.emit(SIGNAL("disappearedFile"), path)
        # if we have new data products, send them to the main window
        return self.makeDataProducts(iter(newstuff.items()))