diff --git a/integrator/base.py b/integrator/base.py
index 90079b5..6a84b55 100644
--- a/integrator/base.py
+++ b/integrator/base.py
@@ -22,13 +22,15 @@ Base implementation for accessing external content objects.
$Id$
"""
+import os
from zope.app.container.contained import Contained
from zope.cachedescriptors.property import Lazy
from zope import component
from zope.interface import implements
-from cybertools.integrator.interfaces import IContainerFactory, IFileFactory
-from cybertools.integrator.interfaces import IReadContainer, IFile, IImage
+from cybertools.integrator.interfaces import IContainerFactory
+from cybertools.integrator.interfaces import IItemFactory, IFileFactory
+from cybertools.integrator.interfaces import IReadContainer, IItem, IFile, IImage
# proxy base (sample) classes
@@ -37,14 +39,20 @@ class ReadContainer(Contained):
implements(IReadContainer)
- factoryName = 'sample'
__parent__ = None
+ factoryName = 'sample'
+
+ icon = 'folder'
def __init__(self, address, **kw):
self.address = address
for k, v in kw.items():
setattr(self, k, v)
+ @Lazy
+ def itemFactory(self):
+ return component.getUtility(IItemFactory, name=self.factoryName)
+
@Lazy
def fileFactory(self):
return component.getUtility(IFileFactory, name=self.factoryName)
@@ -82,14 +90,24 @@ class ReadContainer(Contained):
has_key = __contains__
-class File(object):
+class Item(object):
- implements(IFile)
+ implements(IItem)
contentType = None
- data = None
+ icon = 'item'
__parent__ = None
+ def __init__(self, address, **kw):
+ self.address = address
+ for k, v in kw.items():
+ setattr(self, k, v)
+
+
+class File(Item):
+
+ implements(IFile)
+
def __init__(self, address, contentType, **kw):
self.address = address
self.contentType = contentType
@@ -104,11 +122,17 @@ class File(object):
def getSize(self):
return len(self.data)
+ @property
+ def icon(self):
+ return (mimeTypes.get(self.contentType) or ['unknown'])[0]
-def Image(File):
+
+class Image(File):
implements(IImage)
+ icon = 'image'
+
def getImageSize(self):
return 0, 0
@@ -130,9 +154,33 @@ class ContainerFactory(Factory):
proxyClass = ReadContainer
+class ItemFactory(Factory):
+
+ implements(IItemFactory)
+
+ proxyClass = Item
+
+
class FileFactory(Factory):
implements(IFileFactory)
proxyClass = File # real implementations should also care about images
+
+# provide a dictionary of MIME types with extensions = icon names
+
+class MimeTypes(dict):
+
+ def __init__(self):
+ super(MimeTypes, self).__init__()
+ fn = os.path.join(os.path.dirname(__file__), 'mime.types')
+ mtFile = open(fn, 'r')
+ for line in mtFile:
+ line = line.strip()
+ if line:
+ parts = line.split()
+ self[parts[0]] = parts[1:]
+ mtFile.close()
+
+mimeTypes = MimeTypes()
diff --git a/integrator/bscw.py b/integrator/bscw.py
index 90772e2..f75e39f 100644
--- a/integrator/bscw.py
+++ b/integrator/bscw.py
@@ -30,8 +30,8 @@ from zope.cachedescriptors.property import Lazy
from zope.contenttype import guess_content_type
from zope.interface import implements, Attribute
-from cybertools.integrator.base import ContainerFactory, FileFactory
-from cybertools.integrator.base import ReadContainer, File, Image
+from cybertools.integrator.base import ContainerFactory, ItemFactory, FileFactory
+from cybertools.integrator.base import ReadContainer, Item, File, Image
from cybertools.text import mimetypes
@@ -62,7 +62,10 @@ class ReadContainer(ReadContainer):
def data(self):
data = self.server.get_attributes(self.address,
['__class__', 'type', 'id', 'name', 'descr', 'url_link'], 1, True)
- return dict((item['id'], item) for item in data[1])
+ if len(data) > 1:
+ return dict((item['id'], item) for item in data[1])
+ else:
+ return {}
def keys(self):
return self.data.keys()
@@ -79,14 +82,16 @@ class ReadContainer(ReadContainer):
if key not in self.data:
return default
item = self.data[key]
- if 'Folder' in item['__class__']:
+ itemType = item['__class__'].split('.')[-1]
+ if itemType == 'Folder':
return self.containerFactory(item['id'], server=self.server,
name=item['name'])
- elif 'Document' in item['__class__']:
- return self.fileFactory(item['id'], item['type'], server=self.server,
- name=item['name'])
+ elif itemType == 'Document':
+ return self.fileFactory(item['id'], contentType=item['type'],
+ server=self.server, name=item['name'])
else:
- return OtherObject(item['id'], None, server=self.server, name=item['name'])
+ return self.itemFactory(item['id'], server=self.server,
+ name=item['name'], type=itemType)
def values(self):
return [self.get(k) for k in self]
@@ -101,6 +106,13 @@ class ReadContainer(ReadContainer):
return key in self.keys()
+class Item(Item):
+
+ @property
+ def icon(self):
+ return self.type.lower()
+
+
class File(File):
contentType = None
@@ -113,11 +125,6 @@ class File(File):
return 0
-class OtherObject(File):
-
- data = u''
-
-
# factory classes
class ContainerFactory(ContainerFactory):
@@ -131,10 +138,18 @@ class ContainerFactory(ContainerFactory):
return self.proxyClass(address, server=server, **kw)
+class ItemFactory(ItemFactory):
+
+ proxyClass = Item
+
+
class FileFactory(FileFactory):
def __call__(self, address, **kw):
- contentType = kw.pop('type', 'application/octet-stream')
- obj = File(address, contentType, **kw)
+ contentType = kw.pop('contentType', 'application/octet-stream')
+ if contentType.startswith('image/'):
+ obj = Image(address, contentType, **kw)
+ else:
+ obj = File(address, contentType, **kw)
obj.contentType = contentType
return obj
diff --git a/integrator/bscw.txt b/integrator/bscw.txt
index 16fd44c..768ea20 100644
--- a/integrator/bscw.txt
+++ b/integrator/bscw.txt
@@ -20,15 +20,33 @@ repository for testing purposes.
>>> server.get_attributes('4', standardAttributes + ['containers'], 1, True)
[{...'name': 'public'...}, [{...'name': 'Introduction'...}]]
-Access via read container and file proxies
-------------------------------------------
+Access via read container and item/file proxies
+-----------------------------------------------
+
+Let's first register the proxy factory utilities.
>>> from zope import component
- >>> from cybertools.integrator.bscw import ContainerFactory
+ >>> from cybertools.integrator.bscw import ContainerFactory, ItemFactory, FileFactory
>>> component.provideUtility(ContainerFactory(), name='bscw')
+ >>> component.provideUtility(ItemFactory(), name='bscw')
+ >>> component.provideUtility(FileFactory(), name='bscw')
+
+We can now access the root object of the BSCW repository
>>> from cybertools.integrator.interfaces import IContainerFactory
>>> root = component.getUtility(IContainerFactory, name='bscw')('4', server=server)
- >>> sorted(root)
- ['bs_5']
+ >>> sorted(root.items())
+ [('bs_5', <...ReadContainer object...>)]
+
+ >>> root.icon
+ 'folder'
+
+ >>> bs_5 = root['bs_5']
+ >>> data = server.get_attributes('bs_5',
+ ... ['__class__', 'type', 'id', 'name', 'descr', 'url_link'], 1, True)
+
+ >>> bs_5.items()
+ []
+ >>> bs_5.icon
+ 'folder'
diff --git a/integrator/filesystem.py b/integrator/filesystem.py
index 3ac7c12..25bd605 100644
--- a/integrator/filesystem.py
+++ b/integrator/filesystem.py
@@ -98,6 +98,7 @@ class File(File):
class Image(File):
width = height = 0
+ icon = 'image'
def getImageSize(self):
return self.width, self.height
diff --git a/integrator/filesystem.txt b/integrator/filesystem.txt
index 7c25f41..bc8ecfe 100644
--- a/integrator/filesystem.txt
+++ b/integrator/filesystem.txt
@@ -39,12 +39,16 @@ Accessing Objects in the Filesystem
'application/x-tar'
>>> file.getSize()
432L
+ >>> file.icon
+ 'tar'
>>> logo = sub['loops_logo.png']
>>> logo.contentType
'image/png'
>>> logo.getImageSize()
(145, 42)
+ >>> logo.icon
+ 'image'
>>> html = top['index.html']
>>> html.contentType
@@ -55,4 +59,6 @@ Accessing Objects in the Filesystem
Subdirectory
Demo...