From a932deff3e2e5156e6d8daa0697a78872c57271b Mon Sep 17 00:00:00 2001 From: helmutm Date: Sun, 11 May 2008 16:55:17 +0000 Subject: [PATCH] work in progress: BSCW interface git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@2592 fd906abe-77d9-0310-91a1-e0d9ade77398 --- integrator/README.txt | 2 +- integrator/bscw.py | 55 +++++++++++--------- integrator/bscw.txt | 34 +++++++++++++ integrator/testing/bscw.py | 102 +++++++++++++++++++++++++++++++++++++ integrator/tests.py | 4 +- 5 files changed, 170 insertions(+), 27 deletions(-) create mode 100644 integrator/bscw.txt create mode 100644 integrator/testing/bscw.py diff --git a/integrator/README.txt b/integrator/README.txt index fb943de..18154fa 100644 --- a/integrator/README.txt +++ b/integrator/README.txt @@ -22,7 +22,7 @@ Let's do some basic set up Accessing Objects in the Filesystem -======================================= +=================================== >>> top = component.getUtility(IContainerFactory, name='filesystem')(testDir) >>> sorted(top) diff --git a/integrator/bscw.py b/integrator/bscw.py index aad64f2..90772e2 100644 --- a/integrator/bscw.py +++ b/integrator/bscw.py @@ -35,12 +35,28 @@ from cybertools.integrator.base import ReadContainer, File, Image from cybertools.text import mimetypes +baseAttributes = ['__class__', 'name', 'id', 'descr', 'notes', + 'bound_sub_artifacts', 'creator', 'owner', 'owners', + 'ctime', 'mtime', 'atime', 'lastEvent', 'createEvent', + 'lastChange', 'lastMove', 'containers', 'access'] + +standardAttributes = ['__class__', 'name', 'id', 'descr', 'mtime'] + +additionalAttributes = ['banner', 'moderated', 'ratings'] + +documentAttributes = ['vid', 'vstore', 'file_extensions', 'size', 'encoding', 'type'] + +urlAttributes = ['url_link', 'last_verified', 'last_error', 'content_length', + 'content_type', 'content_encoding', 'last_modified'] + +classes = ['cl_core.Folder', 'cl_core.Document', 'cl_core.URL', ] + + # proxy classes class ReadContainer(ReadContainer): factoryName = 'bscw' - data = None @Lazy def data(self): @@ -64,12 +80,13 @@ class ReadContainer(ReadContainer): return default item = self.data[key] if 'Folder' in item['__class__']: - return self.containerFactory(item['id'], server=self.server) + return self.containerFactory(item['id'], server=self.server, + name=item['name']) elif 'Document' in item['__class__']: - return self.fileFactory(item['id'], server=self.server, - type=item['type']) + return self.fileFactory(item['id'], item['type'], server=self.server, + name=item['name']) else: - return OtherObject(item['id'], server=self.server) + return OtherObject(item['id'], None, server=self.server, name=item['name']) def values(self): return [self.get(k) for k in self] @@ -93,15 +110,7 @@ class File(File): data = property(getData) def getSize(self): - return os.stat(self.address)[stat.ST_SIZE] - - -class Image(File): - - width = height = 0 - - def getImageSize(self): - return self.width, self.height + return 0 class OtherObject(File): @@ -116,20 +125,16 @@ class ContainerFactory(ContainerFactory): proxyClass = ReadContainer def __call__(self, address, **kw): - server = ServerProxy(address) - name = kw.pop('name', '') - return self.proxyClass(name, server=server, **kw) + 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) class FileFactory(FileFactory): def __call__(self, address, **kw): - contentType = kw.pop('type', None) - width = height = 0 + contentType = kw.pop('type', 'application/octet-stream') obj = File(address, contentType, **kw) - if contentType.startswith('image/'): - return Image(address, contentType=contentType, - width=width, height=height, **kw) - else: - obj.contentType = contentType - return obj + obj.contentType = contentType + return obj diff --git a/integrator/bscw.txt b/integrator/bscw.txt new file mode 100644 index 0000000..ccb38d9 --- /dev/null +++ b/integrator/bscw.txt @@ -0,0 +1,34 @@ +========================================= +Integrating objects from external systems +========================================= + +Integration of external sources. + + ($Id$) + + +Accessing Objects on a Remote BSCW Repository +============================================= + +In fact we do not access a remote repository but just a dummy (fake) +repository for testing purposes. + + >>> from cybertools.integrator.testing.bscw import BSCWServer, sampleObjects + >>> from cybertools.integrator.bscw import standardAttributes + >>> server = BSCWServer(sampleObjects) + + >>> server.get_attributes('4', standardAttributes + ['containers'], 1, True) + [{...'name': 'public'...}, [{...'name': 'Introduction'...}]] + +Access via read container and file proxies +------------------------------------------ + + >>> from zope import component + >>> from cybertools.integrator.bscw import ContainerFactory + >>> component.provideUtility(ContainerFactory(), name='bscw') + + >>> from cybertools.integrator.interfaces import IContainerFactory + >>> root = component.getUtility(IContainerFactory, name='bscw')('4', server=server) + + >>> sorted(root) + ['bs_5'] diff --git a/integrator/testing/bscw.py b/integrator/testing/bscw.py new file mode 100644 index 0000000..61828c8 --- /dev/null +++ b/integrator/testing/bscw.py @@ -0,0 +1,102 @@ +# +# Copyright (c) 2008 Helmut Merz helmutm@cy55.de +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +""" +Fake BSCW repository for testing purposes. + +$Id$ +""" + +from xmlrpclib import Fault + +from cybertools.integrator import bscw + + +class Artifact(dict): + + attributes = bscw.baseAttributes + repository = None + + def __init__(self, id, **kw): + if not id.startswith('bs_'): + id = 'bs_' + id + self.id = self['id'] = self['__id__'] = id + self.children = kw.pop('children', []) + self['__class__'] = kw.pop('__class__', 'cl_core.Folder') + self.update(kw) + + def getData(self, attrs): + return dict((key, self[key]) for key in attrs if key in self) + + +class BSCWRepository(dict): + + def __init__(self, *objs): + for obj in objs: + self[obj.id] = obj + obj.repository = self + self.updateContainersAttribute() + + def get(self, key, default=None): + if not key.startswith('bs_'): + key = 'bs_' + key + return super(BSCWRepository, self).get(key, default) + + def updateContainersAttribute(self): + for obj in self.values(): + for c in obj.children: + child = self.get(c) + if child is not None: + containerInfo = dict(__id__=child.id, name=child['name']) + child.setdefault('containers', []).append(containerInfo) + + +sampleObjects = BSCWRepository( + Artifact('4', name='public', descr='Public Repository', children=['5'], + containers=[dict(__id__='4711', name='Community of Anonymous')]), + Artifact('5', name='Introduction', descr='Introduction to BSCW'), +) + + +class BSCWServer(object): + + def __init__(self, objects): + self. objects = objects + + def get_attributes(self, id=None, attribute_names=['__id__', 'name'], depth=0, + nested=False, offset=0, number=0, sorted_by=None): + obj = self.objects.get(id) + if obj is None: + raise Fault(10101, 'Bad object id: %s' % id) + result = [obj.getData(attribute_names)] + if nested: + for level in range(depth): + for id in obj.children: + result.append(self.get_attributes(id, attribute_names, + depth-1, nested, offset, number, sorted_by)) + return result + + def get_attributenames(self, __class__): + return baseAttributes + + def get_document(self, id, version_id): + return '' + + def get_path(id): + return self.get_attributes(id, ['containers'])[0].get('containers', []) + diff --git a/integrator/tests.py b/integrator/tests.py index f24ef84..1cef3ba 100755 --- a/integrator/tests.py +++ b/integrator/tests.py @@ -9,6 +9,8 @@ from zope.interface.verify import verifyClass baseDir = os.path.dirname(__file__) testDir = os.path.join(baseDir, 'testing', 'data') +flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS + class Test(unittest.TestCase): "Basic tests for the cybertools.integrator package." @@ -18,10 +20,10 @@ class Test(unittest.TestCase): def test_suite(): - flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS return unittest.TestSuite(( unittest.makeSuite(Test), DocFileSuite('README.txt', optionflags=flags), + DocFileSuite('bscw.txt', optionflags=flags), )) if __name__ == '__main__':