""" Filereader.py: Abstracts away the reading and detection of files and directories. It will have succeeded if it presents a unified interface to the program by abstracting away most of the fact that local methods of access and foreign methods of access differ. """ import os, sys, gtk, gobject, pwd import mime, fsutil from helpers import Property _IconTheme = gtk.icon_theme_get_default() _SVG = gtk.ICON_LOOKUP_FORCE_SVG _UNITS = {0: ' B', 1: ' KB', 2: ' MB', 3: ' GB'} _DIR_ICON = _IconTheme.load_icon(mime.directory.icon, 16, _SVG) class FileReader: """Takes a Path() object and returns a FileReader.""" def __init__(self, path): self.cwd = path.name self.path = path self.refresh() def chdir(self, path): self.cwd = path.name self.path = path self.refresh() def __repr__(self): return "" % (self.cwd, len(self.files), len(self.directories)) def read(self): for ent in self.directories + self.files: yield ent class LocalFileReader(FileReader): def refresh(self): self.filehash = {} self.dirhash = {} l = self.path.listdir() l.sort() for entry in l: path = Path(os.path.join(self.path.path, entry)) if path.isdir(): self.dirhash[entry] = Directory(path) elif path.isfile(): self.filehash[entry] = File(path) self.files = list(self.filehash.values()) self.directories = list(self.dirhash.values()) self.files.sort(key=lambda x:x.name) self.directories.sort(key=lambda x:x.name) class FTPFileReader(FileReader): pass class SFTPFileReader(FileReader): pass class SCPFileReader(FileReader): pass class Path(gobject.GObject): def __init__(self, path): gobject.GObject.__init__(self) if isinstance(path, unicode) or isinstance(path, str): self.path = fsutil.normalize_path(path) self.name = self.path.split(os.path.sep)[-1] else: self.path = path self.name = path.name if not self.name: self.name = '/' @Property def icon(): def fget(self): if self.isHome(): return 'gnome-fs-home' if self.isDesktop(): return 'gnome-fs-desktop' if self.name == '/': return mime.volume.icon return False @Property def parent(): def fget(self): if self.path == '/': return None elif not self.path.rfind('/'): return Path('/') return Path(self.path[:self.path.rfind('/')]) def parents(self): p = self while p: yield p p = p.parent def isHome(self): home = pwd.getpwuid(os.getuid()).pw_dir return os.path.samefile(home, self.path) def isDesktop(self): home = pwd.getpwuid(os.getuid()).pw_dir return os.path.samefile(os.path.join(home, 'Desktop'), self.path) def escapedName(self): return self.name.replace('&', '&') def isdir(self): return os.path.isdir(self.path) def isfile(self): return os.path.isfile(self.path) def listdir(self): if os.path.isdir(self.path): return os.listdir(self.path) # implement some string functionality so Paths can be used # as strings somewhat transparently def rfind(self, *args): return self.path.rfind(*args) def __getitem__(self, i): return self.path[i] def __getslice__(self, i, j): return self.path[i:j] def __str__(self): return self.path def __repr__(self): return '' % self.path def __eq__(self, other): return self.path == other.path class DirectoryEntry: def __init__(self, path): self.path = path self._path = unicode(path) self.name = os.path.basename(self._path) self.size = os.path.getsize(self._path) # if we are a directory f = True if not self.name: f = False self.name = os.path.split(self._path)[-1] self.mime = mime.directory if f: self.mime = mime.MimeType(self.name) self.icon = self.loadIcon() if self.name.startswith('.'): self.isHidden = True else: self.isHidden = False def loadIcon(self): return _IconTheme.load_icon(self.mime.icon, 16, _SVG) def humanSize(self): if self.isDirectory: return '' hsize = float(self.size) magnitude = 0 while hsize > 1024: hsize /= 1024.0 magnitude+= 1 units = _GET_UNITS(magnitude) return '%.1f%s' % (hsize, units) def __repr__(self): return '<%s: %s (%s)>' % (self.__class__.__name__, self.name, self.mime.type) class File(DirectoryEntry): isFile = True isDirectory = False class Directory(DirectoryEntry): isFile = False isDirectory = True def loadIcon(self): return _DIR_ICON # Convenience functions and constants def _GET_UNITS(magnitude): if not isinstance(magnitude, int) or magnitude > 3: return '(?)' return _UNITS[magnitude] if __name__ == '__main__': import sys if len(sys.argv) > 1: path = sys.argv[1] else: path = '.' lfr = LocalFileReader(Path(path)) print repr(lfr) for entry in lfr.files + lfr.directories: print '> ' + repr(entry)