provide additional common attributes for proxy objects

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@2615 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2008-05-23 10:20:44 +00:00
parent 7ef8e4f229
commit 665e9bf650
6 changed files with 205 additions and 38 deletions

View file

@ -23,6 +23,7 @@ $Id$
"""
import os
from urllib import urlencode
from zope.app.container.contained import Contained
from zope.cachedescriptors.property import Lazy
from zope import component
@ -35,20 +36,40 @@ from cybertools.integrator.interfaces import IReadContainer, IItem, IFile, IImag
# proxy base (sample) classes
class ReadContainer(Contained):
implements(IReadContainer)
class ProxyBase(object):
__parent__ = None
factoryName = 'sample'
icon = 'folder'
internalPath = ''
externalUrlInfo = None
description = u''
authors = ()
created = modified = None
def __init__(self, address, **kw):
self.address = address
for k, v in kw.items():
setattr(self, k, v)
@Lazy
def title(self):
if self.internalPath:
return self.internalPath.rsplit('/', 1)[-1]
return self.address.rsplit(os.path.sep, 1)[-1]
class ReadContainer(ProxyBase, Contained):
implements(IReadContainer)
icon = 'folder'
@Lazy
def properties(self):
return {}
@Lazy
def itemFactory(self):
return component.getUtility(IItemFactory, name=self.factoryName)
@ -90,29 +111,21 @@ class ReadContainer(Contained):
has_key = __contains__
class Item(object):
class Item(ProxyBase, object):
implements(IItem)
contentType = 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
super(File, self).__init__(address, **kw)
self.contentType = contentType
for k, v in kw.items():
setattr(self, k, v)
def getData(self, num=None):
return ''
@ -137,6 +150,19 @@ class Image(File):
return 0, 0
# URL info
class ExternalUrlInfo(object):
def __init__(self, baseUrl='', path='', params=None):
self.baseUrl, self.path = baseUrl.strip('/'), path.strip('/')
self.params = params or {}
def __str__(self):
params = self.params and ('?' + urlencode(self.params)) or ''
return '%s/%s%s' % (self.baseUrl, self.path, params)
# factory base (sample) classes
class Factory(object):

View file

@ -32,6 +32,7 @@ from zope.interface import implements, Attribute
from cybertools.integrator.base import ContainerFactory, ItemFactory, FileFactory
from cybertools.integrator.base import ReadContainer, Item, File, Image
from cybertools.integrator.base import ExternalUrlInfo
from cybertools.text import mimetypes
@ -54,14 +55,40 @@ classes = ['cl_core.Folder', 'cl_core.Document', 'cl_core.URL', ]
# proxy classes
class ReadContainer(ReadContainer):
class BSCWProxyBase(object):
@Lazy
def externalUrlInfo(self):
id = self.address
if id.startswith('bs_'):
id = id[3:]
return ExternalUrlInfo(self.baseUrl, id)
@Lazy
def title(self):
return self.properties['name']
@Lazy
def description(self):
return self.properties.get('descr', u'')
class ReadContainer(BSCWProxyBase, ReadContainer):
factoryName = 'bscw'
@Lazy
def data(self):
data = self.server.get_attributes(self.address,
def properties(self):
return self.attributes[0]
@Lazy
def attributes(self):
return self.server.get_attributes(self.address,
['__class__', 'type', 'id', 'name', 'descr', 'url_link'], 1, True)
@Lazy
def data(self):
data = self.attributes
if len(data) > 1:
return dict((item['id'], item) for item in data[1])
else:
@ -83,15 +110,16 @@ class ReadContainer(ReadContainer):
return default
item = self.data[key]
itemType = item['__class__'].split('.')[-1]
internalPath = '/'.join((self.internalPath, key)).strip('/')
params = dict(server=self.server, internalPath=internalPath,
properties=item, baseUrl=self.baseUrl)
if itemType == 'Folder':
return self.containerFactory(item['id'], server=self.server,
name=item['name'])
return self.containerFactory(item['id'], **params)
elif itemType == 'Document':
return self.fileFactory(item['id'], contentType=item['type'],
server=self.server, name=item['name'])
**params)
else:
return self.itemFactory(item['id'], server=self.server,
name=item['name'], type=itemType)
return self.itemFactory(item['id'], **params)
def values(self):
return [self.get(k) for k in self]
@ -106,18 +134,18 @@ class ReadContainer(ReadContainer):
return key in self.keys()
class Item(Item):
class Item(BSCWProxyBase, Item):
@property
def icon(self):
return self.type.lower()
class File(File):
class File(BSCWProxyBase, File):
contentType = None
def getData(self):
def getData(self, num=None):
return self.server.get_document()
data = property(getData)
@ -135,7 +163,9 @@ class ContainerFactory(ContainerFactory):
server = kw.pop('server')
if isinstance(server, basestring): # just a URL, resolve for XML-RPC
server = ServerProxy(server)
return self.proxyClass(address, server=server, **kw)
baseUrl = server
baseUrl = kw.pop('baseUrl', '')
return self.proxyClass(address, server=server, baseUrl=baseUrl, **kw)
class ItemFactory(ItemFactory):

View file

@ -34,13 +34,29 @@ Let's first register the proxy factory utilities.
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)
>>> root = component.getUtility(IContainerFactory, name='bscw')('4', server=server,
... baseUrl='http://localhost/bscw.cgi/')
>>> sorted(root.items())
[('bs_5', <...ReadContainer object...>)]
>>> root.address
'4'
>>> root.internalPath
''
>>> root.icon
'folder'
>>> root.properties
{...'name': 'public'...}
>>> root.title
'public'
>>> root.description
'Public Repository'
>>> str(root.externalUrlInfo)
'http://localhost/bscw.cgi/4'
Let's also have a look at the item contained in the root object.
>>> bs_5 = root['bs_5']
>>> data = server.get_attributes('bs_5',
@ -48,5 +64,15 @@ We can now access the root object of the BSCW repository
>>> bs_5.items()
[]
>>> bs_5.address
'bs_5'
>>> bs_5.internalPath
'bs_5'
>>> bs_5.icon
'folder'
>>> bs_5.properties
{...'name': 'Introduction'...}
>>> str(bs_5.externalUrlInfo)
'http://localhost/bscw.cgi/5'

View file

@ -60,10 +60,13 @@ class ReadContainer(ReadContainer):
if key not in self.keys():
return default
path = os.path.join(self.address, key)
internalPath = '/'.join((self.internalPath, key)).strip('/')
if os.path.isdir(path):
return self.containerFactory(path, __parent__=self.__parent__)
return self.containerFactory(path, internalPath=internalPath,
__parent__=self.__parent__)
else:
return self.fileFactory(path, __parent__=self.__parent__)
return self.fileFactory(path, internalPath=internalPath,
__parent__=self.__parent__)
def values(self):
return [self.get(k) for k in self]

View file

@ -24,33 +24,81 @@ Let's do some basic set up
Accessing Objects in the Filesystem
===================================
We access the top-level object (a directory) by calling the container (proxy)
factory with the address (path) leading to the directory.
>>> top = component.getUtility(IContainerFactory, name='filesystem')(testDir)
This top-level object is a container with some sub-objects, that may be
containers themeselves or terminal objects (items or files).
>>> sorted(top)
['index.html', 'sub']
>>> len(top)
2
A proxy provides a set of attributes that may be used for viewing the
object or navigating to it.
>>> top.address
'...data'
>>> top.internalPath
''
>>> top.icon
'folder'
>>> top.properties
{}
>>> top.title
'data'
The external URL information may be used for directly linking to the
external object - in the case of filesystem objects this is not possible
in a general way, so this attribute is always None.
>>> top.externalUrlInfo is None
True
Let's now have a look at the sub-objects found in the top-level container.
>>> sub = top['sub']
>>> sorted(sub)
['demo.tgz', 'index.html', 'loops_logo.png']
>>> sub.address
'...sub'
>>> sub.internalPath
'sub'
>>> sub.icon
'folder'
>>> sub.properties
{}
>>> sub.externalUrlInfo is None
True
A file object has additional attributes/methods.
>>> file = sub['demo.tgz']
>>> file.address
'...demo.tgz'
>>> file.internalPath
'sub/demo.tgz'
>>> file.icon
'tar'
>>> file.contentType
'application/x-tar'
>>> file.getSize()
432L
>>> file.icon
'tar'
>>> logo = sub['loops_logo.png']
>>> logo.internalPath
'sub/loops_logo.png'
>>> logo.icon
'image'
>>> logo.contentType
'image/png'
>>> logo.getImageSize()
(145, 42)
>>> logo.icon
'image'
>>> html = top['index.html']
>>> html.internalPath
'index.html'
>>> html.contentType
'text/html'
>>> print html.data

View file

@ -29,9 +29,39 @@ from zope.interface import Interface, Attribute
class IProxy(Interface):
""" An object that represents an external object and provides access
to it.
"""
address = Attribute('An external specifier (a name, path, URL, ...) '
'that may be used to access the external object.')
internalPath = Attribute('A relativ path leading to an internal '
'representation of the represented object.')
icon = Attribute('The name of an icon that may be used for symbolizing '
'this object.')
'the represented object.')
properties = Attribute('A dictionary with attributes/properties '
'characteristic for the type of object the proxy represents.')
externalUrlInfo = Attribute('Information necessary for building URLs that link '
'directly to the object the proxy represents (optional).')
title = Attribute('A short string giving basic information about the object.')
description = Attribute('A somewhat longer descriptive information.')
url = Attribute('An explicit target URL (optional).')
authors = Attribute('A list of names of persons who worked on this object.')
create = Attribute('A datetime object denoting the data/time of object '
'creation.')
modified = Attribute('A datetime object denoting the data/time of last '
'modification of the object.')
class IExternalUrlInfo(Interface):
""" Information necessary to build URLs to external objects.
"""
baseUrl = Attribute('The base part of the URL, including the protocol and '
'the server part + optionally a constant part of the path.')
path = Attribute('The relative path leading to the object.')
params = Attribute('A dictionary providing a parameter set that will '
'be appended urlencoded to the base URL.')
class IReadContainer(IProxy, IReadContainer):
@ -40,19 +70,23 @@ class IReadContainer(IProxy, IReadContainer):
class IItem(IProxy, Interface):
""" A terminal kind of object, i.e. not a container of other objects.
""" A proxy for a terminal kind of object, i.e. not a container of
other objects.
"""
class IFile(IItem, IFile, IFileContent):
data = Attribute('The data contained in the file.')
contentType = Attribute('The MIME type of the object.')
def getData(num):
def getData(num=None):
""" Return num bytes from the file`s data.
"""
# proxy factories
class IProxyFactory(Interface):
""" Creates proxy objects for external objects.
"""