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 import os
from urllib import urlencode
from zope.app.container.contained import Contained from zope.app.container.contained import Contained
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope import component from zope import component
@ -35,20 +36,40 @@ from cybertools.integrator.interfaces import IReadContainer, IItem, IFile, IImag
# proxy base (sample) classes # proxy base (sample) classes
class ReadContainer(Contained): class ProxyBase(object):
implements(IReadContainer)
__parent__ = None __parent__ = None
factoryName = 'sample' factoryName = 'sample'
icon = 'folder' internalPath = ''
externalUrlInfo = None
description = u''
authors = ()
created = modified = None
def __init__(self, address, **kw): def __init__(self, address, **kw):
self.address = address self.address = address
for k, v in kw.items(): for k, v in kw.items():
setattr(self, k, v) 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 @Lazy
def itemFactory(self): def itemFactory(self):
return component.getUtility(IItemFactory, name=self.factoryName) return component.getUtility(IItemFactory, name=self.factoryName)
@ -90,29 +111,21 @@ class ReadContainer(Contained):
has_key = __contains__ has_key = __contains__
class Item(object): class Item(ProxyBase, object):
implements(IItem) implements(IItem)
contentType = None
icon = 'item' icon = 'item'
__parent__ = None __parent__ = None
def __init__(self, address, **kw):
self.address = address
for k, v in kw.items():
setattr(self, k, v)
class File(Item): class File(Item):
implements(IFile) implements(IFile)
def __init__(self, address, contentType, **kw): def __init__(self, address, contentType, **kw):
self.address = address super(File, self).__init__(address, **kw)
self.contentType = contentType self.contentType = contentType
for k, v in kw.items():
setattr(self, k, v)
def getData(self, num=None): def getData(self, num=None):
return '' return ''
@ -137,6 +150,19 @@ class Image(File):
return 0, 0 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 # factory base (sample) classes
class Factory(object): 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 ContainerFactory, ItemFactory, FileFactory
from cybertools.integrator.base import ReadContainer, Item, File, Image from cybertools.integrator.base import ReadContainer, Item, File, Image
from cybertools.integrator.base import ExternalUrlInfo
from cybertools.text import mimetypes from cybertools.text import mimetypes
@ -54,14 +55,40 @@ classes = ['cl_core.Folder', 'cl_core.Document', 'cl_core.URL', ]
# proxy classes # 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' factoryName = 'bscw'
@Lazy @Lazy
def data(self): def properties(self):
data = self.server.get_attributes(self.address, return self.attributes[0]
@Lazy
def attributes(self):
return self.server.get_attributes(self.address,
['__class__', 'type', 'id', 'name', 'descr', 'url_link'], 1, True) ['__class__', 'type', 'id', 'name', 'descr', 'url_link'], 1, True)
@Lazy
def data(self):
data = self.attributes
if len(data) > 1: if len(data) > 1:
return dict((item['id'], item) for item in data[1]) return dict((item['id'], item) for item in data[1])
else: else:
@ -83,15 +110,16 @@ class ReadContainer(ReadContainer):
return default return default
item = self.data[key] item = self.data[key]
itemType = item['__class__'].split('.')[-1] 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': if itemType == 'Folder':
return self.containerFactory(item['id'], server=self.server, return self.containerFactory(item['id'], **params)
name=item['name'])
elif itemType == 'Document': elif itemType == 'Document':
return self.fileFactory(item['id'], contentType=item['type'], return self.fileFactory(item['id'], contentType=item['type'],
server=self.server, name=item['name']) **params)
else: else:
return self.itemFactory(item['id'], server=self.server, return self.itemFactory(item['id'], **params)
name=item['name'], type=itemType)
def values(self): def values(self):
return [self.get(k) for k in self] return [self.get(k) for k in self]
@ -106,18 +134,18 @@ class ReadContainer(ReadContainer):
return key in self.keys() return key in self.keys()
class Item(Item): class Item(BSCWProxyBase, Item):
@property @property
def icon(self): def icon(self):
return self.type.lower() return self.type.lower()
class File(File): class File(BSCWProxyBase, File):
contentType = None contentType = None
def getData(self): def getData(self, num=None):
return self.server.get_document() return self.server.get_document()
data = property(getData) data = property(getData)
@ -135,7 +163,9 @@ class ContainerFactory(ContainerFactory):
server = kw.pop('server') server = kw.pop('server')
if isinstance(server, basestring): # just a URL, resolve for XML-RPC if isinstance(server, basestring): # just a URL, resolve for XML-RPC
server = ServerProxy(server) 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): 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 We can now access the root object of the BSCW repository
>>> from cybertools.integrator.interfaces import IContainerFactory >>> 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()) >>> sorted(root.items())
[('bs_5', <...ReadContainer object...>)] [('bs_5', <...ReadContainer object...>)]
>>> root.address
'4'
>>> root.internalPath
''
>>> root.icon >>> root.icon
'folder' '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'] >>> bs_5 = root['bs_5']
>>> data = server.get_attributes('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.items()
[] []
>>> bs_5.address
'bs_5'
>>> bs_5.internalPath
'bs_5'
>>> bs_5.icon >>> bs_5.icon
'folder' '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(): if key not in self.keys():
return default return default
path = os.path.join(self.address, key) path = os.path.join(self.address, key)
internalPath = '/'.join((self.internalPath, key)).strip('/')
if os.path.isdir(path): if os.path.isdir(path):
return self.containerFactory(path, __parent__=self.__parent__) return self.containerFactory(path, internalPath=internalPath,
__parent__=self.__parent__)
else: else:
return self.fileFactory(path, __parent__=self.__parent__) return self.fileFactory(path, internalPath=internalPath,
__parent__=self.__parent__)
def values(self): def values(self):
return [self.get(k) for k in 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 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) >>> 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) >>> sorted(top)
['index.html', 'sub'] ['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'] >>> sub = top['sub']
>>> sorted(sub) >>> sorted(sub)
['demo.tgz', 'index.html', 'loops_logo.png'] ['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 = sub['demo.tgz']
>>> file.address
'...demo.tgz'
>>> file.internalPath
'sub/demo.tgz'
>>> file.icon
'tar'
>>> file.contentType >>> file.contentType
'application/x-tar' 'application/x-tar'
>>> file.getSize() >>> file.getSize()
432L 432L
>>> file.icon
'tar'
>>> logo = sub['loops_logo.png'] >>> logo = sub['loops_logo.png']
>>> logo.internalPath
'sub/loops_logo.png'
>>> logo.icon
'image'
>>> logo.contentType >>> logo.contentType
'image/png' 'image/png'
>>> logo.getImageSize() >>> logo.getImageSize()
(145, 42) (145, 42)
>>> logo.icon
'image'
>>> html = top['index.html'] >>> html = top['index.html']
>>> html.internalPath
'index.html'
>>> html.contentType >>> html.contentType
'text/html' 'text/html'
>>> print html.data >>> print html.data

View file

@ -29,9 +29,39 @@ from zope.interface import Interface, Attribute
class IProxy(Interface): 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 ' 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): class IReadContainer(IProxy, IReadContainer):
@ -40,19 +70,23 @@ class IReadContainer(IProxy, IReadContainer):
class IItem(IProxy, Interface): 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): class IFile(IItem, IFile, IFileContent):
data = Attribute('The data contained in the file.')
contentType = Attribute('The MIME type of the object.') contentType = Attribute('The MIME type of the object.')
def getData(num): def getData(num=None):
""" Return num bytes from the file`s data. """ Return num bytes from the file`s data.
""" """
# proxy factories
class IProxyFactory(Interface): class IProxyFactory(Interface):
""" Creates proxy objects for external objects. """ Creates proxy objects for external objects.
""" """