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) |