Browse Source

make the name/mimetype handling more generic so that other modules

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
John-Mark Gurney 18 years ago
parent
commit
b69eda3b31
3 changed files with 167 additions and 38 deletions
  1. +13
    -38
      FSStorage.py
  2. +71
    -0
      FileDIDL.py
  3. +83
    -0
      ZipStorage.py

+ 13
- 38
FSStorage.py View File

@@ -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:


+ 71
- 0
FileDIDL.py View File

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

+ 83
- 0
ZipStorage.py View File

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

Loading…
Cancel
Save