import os from UserDict import DictMixin import mimetypes from propertyclass import property as dynprop from filebrowser.helpers import url_for class _FileObject(object): def __init__(self, path, root): self.path = os.path.normpath(path) self.root = os.path.normpath(root) assert self.path.startswith(self.root) def __repr__(self): return '<%s %s %r>' % ( self.__class__.__name__, hex(abs(id(self)))[2:], self.path) @property def name(self): return os.path.basename(self.path) @property def relpath(self): return self.path[len(self.root):].lstrip('/\\') @property def mtime(self): return os.path.getmtime(self.path) @property def parent(self): if self.path == self.root: return None return Directory(os.path.dirname(self.path), self.root) def link_to(self, action): return url_for(controller='main', file=self.relpath, action=action) class Directory(_FileObject, DictMixin): isdir = True def __getitem__(self, filename): if not filename: return self newpath = os.path.join(self.path, filename) newpath = os.path.normpath(newpath) if not newpath.startswith(self.path + '/'): raise TypeError( "Bad filename %r: results in %r (not under %r)" % (filename, newpath, self.path)) if os.path.isdir(newpath): return Directory(newpath, self.root) else: return File(newpath, self.root) def keys(self): return os.listdir(self.path) @property def mimetype(self): return 'directory' class File(_FileObject, object): isdir = False @property def mimetype(self): type, encoding = mimetypes.guess_type(self.name) ## FIXME: do something with encoding if not type: return 'application/octet-stream' else: return type class bytes(dynprop): """ Get/set the bytes of this file """ def fget(self): if not self.exists: raise AttributeError( "The file %r doesn't exist" % self.path) f = open(self.path, 'rb') try: return f.read() finally: f.close() def fset(self, value): f = open(self.path, 'wb') try: f.write(value) finally: f.close() def fdel(self, value): os.unlink(self) @property def exists(self): return os.path.exists(self.path) @property def size(self): return os.path.getsize(self.path) def mkdir(self): if self.exists: raise TypeError( "You cannot create directory %r: a file exists there" % self.path) os.mkdir(self.path) # Make this invalid: self.path = None return Directory(self.path)