can use it... we now dynamicly build new classes from the base DIDLLite classes as necessary... Add the startings of the ability to read zip files w/o expanding them... this still needs some glue to work w/ the new world order.. it'll be a bit of work before I have zip in a zip working.. :) [git-p4: depot-paths = "//depot/": change = 808]v0.3
| @@ -4,6 +4,7 @@ | |||
| # $Id$ | |||
| # | |||
| import FileDIDL | |||
| import errno | |||
| import itertools | |||
| import os | |||
| @@ -79,27 +80,7 @@ class FSItem(FSObject, Item): | |||
| self.res.size = os.path.getsize(self.FSpath) | |||
| Item.doUpdate(self) | |||
| class FSVideoItem(FSItem, VideoItem): | |||
| pass | |||
| class FSAudioItem(FSItem, AudioItem): | |||
| pass | |||
| class FSTextItem(FSItem, TextItem): | |||
| pass | |||
| class FSImageItem(FSItem, ImageItem): | |||
| pass | |||
| mimetoklass = { | |||
| 'application/ogg': FSAudioItem, | |||
| 'video': FSVideoItem, | |||
| 'audio': FSAudioItem, | |||
| 'text': FSTextItem, | |||
| 'image': FSImageItem, | |||
| } | |||
| def defFS(path): | |||
| def defFS(path, fobj): | |||
| if os.path.isdir(path): | |||
| # new dir | |||
| return FSDirectory, { 'path': path } | |||
| @@ -110,30 +91,24 @@ def defFS(path): | |||
| log.msg('skipping (not dir or reg): %s' % path) | |||
| return None, None | |||
| fn, ext = os.path.splitext(path) | |||
| ext = ext.lower() | |||
| try: | |||
| mt = mimedict[ext] | |||
| except KeyError: | |||
| log.msg('no mime-type for: %s' % path) | |||
| return None, None | |||
| ty = mt.split('/')[0] | |||
| if mimetoklass.has_key(mt): | |||
| klass = mimetoklass[mt] | |||
| elif mimetoklass.has_key(ty): | |||
| klass = mimetoklass[ty] | |||
| else: | |||
| log.msg('no item for mt: %s' % mt) | |||
| return None, None | |||
| klass, mt = FileDIDL.buildClassMT(FSItem, path) | |||
| return klass, { 'path': path, 'mimetype': mt } | |||
| def dofileadd(cd, parent, path, name): | |||
| klass = None | |||
| try: | |||
| fobj = open(path) | |||
| except: | |||
| fobj = None | |||
| for i in itertools.chain(klassfuns, ( defFS, )): | |||
| try: | |||
| klass, kwargs = i(os.path.join(path, name)) | |||
| try: | |||
| fobj.seek(0) # incase the call expects a clean file | |||
| except: | |||
| pass | |||
| klass, kwargs = i(os.path.join(path, name), fobj) | |||
| if klass is not None: | |||
| break | |||
| except: | |||
| @@ -0,0 +1,71 @@ | |||
| #!/usr/bin/env python | |||
| # Copyright 2006 John-Mark Gurney <gurney_j@resnet.uoregon.edu> | |||
| # | |||
| # $Id$ | |||
| # | |||
| # | |||
| # Convert file information into a DIDL class. Dynamicly generate a new class | |||
| # from a base class and the DIDL class to be determined. | |||
| # | |||
| __all__ = [ 'mimetoclass', 'buildClassMT', 'getClassMT', ] | |||
| import os.path | |||
| import weakref | |||
| from DIDLLite import VideoItem, AudioItem, TextItem, ImageItem | |||
| from twisted.python import log | |||
| from twisted.web import static | |||
| mimedict = static.loadMimeTypes() | |||
| classdict = weakref.WeakValueDictionary() | |||
| mimetoclass = { | |||
| 'application/ogg': AudioItem, | |||
| 'video': VideoItem, | |||
| 'audio': AudioItem, | |||
| 'text': TextItem, | |||
| 'image': ImageItem, | |||
| } | |||
| def getClassMT(name, mimetype = None, fp = None): | |||
| '''Return a tuple of the DIDLLite class and mimetype responsible for the named/mimetyped/fpd file.''' | |||
| if mimetype is None: | |||
| fn, ext = os.path.splitext(name) | |||
| ext = ext.lower() | |||
| try: | |||
| mimetype = mimedict[ext] | |||
| except KeyError: | |||
| log.msg('no mime-type for: %s' % name) | |||
| return None, None | |||
| ty = mimetype.split('/')[0] | |||
| if mimetoclass.has_key(mimetype): | |||
| klass = mimetoclass[mimetype] | |||
| elif mimetoclass.has_key(ty): | |||
| klass = mimetoclass[ty] | |||
| else: | |||
| # XXX - We could fall file -i on it | |||
| log.msg('no item for mimetype: %s' % mimetype) | |||
| return None, None | |||
| return klass, mimetype | |||
| def buildClassMT(baseklass, name, *args, **kwargs): | |||
| klass, mt = getClassMT(name, *args, **kwargs) | |||
| if klass is None: | |||
| return None, None | |||
| try: | |||
| return classdict[(baseklass, klass)], mt | |||
| except KeyError: | |||
| pass | |||
| class ret(baseklass, klass): | |||
| pass | |||
| ret.__name__ = '+'.join(map(lambda x: '%s.%s' % (x.__module__, x.__name__), (baseklass, klass))) | |||
| classdict[(baseklass, klass)] = ret | |||
| return ret, mt | |||
| @@ -0,0 +1,83 @@ | |||
| #!/usr/bin/env python | |||
| # Copyright 2006 John-Mark Gurney <gurney_j@resnet.uroegon.edu> | |||
| # | |||
| # $Id$ | |||
| # | |||
| import os.path | |||
| import zipfile | |||
| from DIDLLite import StorageFolder, Item, VideoItem, AudioItem, TextItem, ImageItem, Resource | |||
| from FSStorage import FSObject, registerklassfun | |||
| def isatpath(f, p): | |||
| if f[:len(p)] != p: | |||
| # First part of path doesn't match, it's not | |||
| return False | |||
| slash = f[len(p):].find('/') | |||
| if slash != -1 and slash != len(f) - len(p) + 1: | |||
| # Another path component, skip it, as long as it's not the char | |||
| return False | |||
| # otherwise, it is at this level | |||
| endtrim = len(f) | |||
| if slash: | |||
| endtrip -= 1 | |||
| return f[len(p):endtrim] | |||
| class ZipChildDir(StorageFolder): | |||
| '''This is to represent a child dir of the zip file.''' | |||
| class ZipFile(FSObject, StorageFolder): | |||
| def __init__(self, *args, **kwargs): | |||
| '''If a zip argument is passed it, use that as the zip archive.''' | |||
| path = kwargs['path'] | |||
| del kwargs['path'] | |||
| StorageFolder.__init__(self, *args, **kwargs) | |||
| FSObject.__init__(self, path) | |||
| # mapping from path to objectID | |||
| self.pathObjmap = {} | |||
| def getdirents(path): | |||
| '''Returns the list of entires for the path, '' is the root path.''' | |||
| lst = self.zip.namelist() | |||
| if path: | |||
| path += '/' | |||
| return filter(lambda x, p = path: isatpath(x, p), lst) | |||
| def doUpdate(self): | |||
| # open the zipfile as necessary. | |||
| self.zip = zipfile.ZipFile(self.FSpath) | |||
| allzipfiles = sets.Set(self.zip.namelist()) | |||
| children = sets.Set(getdirents('')) | |||
| for i in self.pathObjmap.keys(): | |||
| if i not in children: | |||
| # delete | |||
| self.cd.delItem(self.pathObjmap[i]) | |||
| del self.pathObjmap[i] | |||
| for i in children: | |||
| if i in self.pathObjmap: | |||
| continue | |||
| # new object | |||
| if i not in allzipfiles: | |||
| # must be a dir | |||
| else: | |||
| ZipChild(self, i) | |||
| def detectzipfile(path, fobj): | |||
| try: | |||
| z = zipfile.ZipFile(fobj) | |||
| except: | |||
| return None, None | |||
| return ZipFile, {} | |||
| registerklassfun(detectzipfile) | |||