import os, os.path, stat, sys, time import gobject, gtk from threading import Thread class sum_list: def __init__(self, l, name = None): self.the_sum = 0 self.data = list(l) self.name = name for fn, i in self.data: if isinstance(i, sum_list): self.the_sum += i.the_sum else: self.the_sum += i def __str__(self): return self.name+": "+str(self.data) def sort(self): def cmp_fn(a, b): a_dir = isinstance(a[1], sum_list) b_dir = isinstance(b[1], sum_list) if a_dir and not b_dir: return 1 elif b_dir and not a_dir: return -1 elif a_dir: return cmp(a[1].the_sum, b[1].the_sum) else: return cmp(a[1], b[1]) self.data.sort(cmp_fn) class FringWalker( gobject.GObject ): __gsignals__ = { 'list-changed': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)), 'finished': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)), 'progress': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT,gobject.TYPE_INT)), } def __init__(self): gobject.GObject.__init__(self) self.thread = None self.stopsignal = False self.showhidden = False def walk(self,path): self.thread = Thread(None,self._parse,None,(path,)) self.stopsignal = False print "start thread (%s)"%path self.thread.start() def stop(self): if self.thread is None: return if not self.thread.isAlive(): self.thread = None return self.stopsignal = True print "stopping thread:" #self.thread.join() print "ok" def _parse(self,path): """ Parse the root directory """ def progress_fn(c, l, r): # emit signals gtk.gdk.threads_enter() self.emit("progress", c, l) self.emit("list-changed", r) gtk.gdk.threads_leave() r = self._build_tree(path, progress_fn) gtk.gdk.threads_enter() self.emit("finished", r) gtk.gdk.threads_leave() print "finished walking", path def _build_tree(self, path, progress_fn = None): """ Parse directories recursively """ ret = [] tmp_dirs = [] try: # walk files in directory for fn in os.listdir(path): if self.stopsignal: return sum_list([]) if not self.showhidden and fn[0] == '.': continue try: p = os.path.join(path, fn) s = os.lstat(p) except: continue if stat.S_ISDIR(s.st_mode): tmp_dirs.append(fn); elif stat.S_ISREG(s.st_mode): ret.append((fn, s.st_size)) except OSError: pass try: c = 0 for fn in tmp_dirs: c += 1 if self.stopsignal: return sum_list([]) try: p = os.path.join(path, fn) except: continue ret.append((fn, self._build_tree(p))) if not (progress_fn is None): r = sum_list(ret, os.path.split(path)[-1]) r.sort() progress_fn(c, len(tmp_dirs), r) except OSError: pass r = sum_list(ret, os.path.split(path)[-1]) r.sort() return r