=============================================================== loops - Linked Objects for Organization and Processing Services =============================================================== Integration of external sources. ($Id$) Setting up a loops Site and Utilities ===================================== Let's do some basic set up >>> from zope import component, interface >>> from zope.traversing.api import getName >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown >>> site = placefulSetUp(True) and build a simple loops site with a concept manager and some concepts (with a relation registry, a catalog, and all the type machinery - what in real life is done via standard ZCML setup or via local utility configuration): >>> from loops.integrator.testsetup import TestSite >>> t = TestSite(site) >>> concepts, resources, views = t.setup() >>> len(concepts) + len(resources) 18 External Collections ==================== The basis of our work will be ExternalCollection objects, i.e. concepts of the 'extcollection' type. We use an adapter for providing the attributes and methods of the external collect object. >>> from loops.concept import Concept >>> from loops.setup import addObject >>> from loops.integrator.collection import ExternalCollectionAdapter >>> tExternalCollection = concepts['extcollection'] >>> coll01 = addObject(concepts, Concept, 'coll01', ... title=u'Collection One', conceptType=tExternalCollection) >>> aColl01 = ExternalCollectionAdapter(coll01) An external collection carries a set of attributes that control the access to the external system: >>> aColl01.providerName, aColl01.baseAddress, aColl01.address, aColl01.pattern (None, None, None, None) >>> from loops.integrator.testsetup import dataDir >>> aColl01.baseAddress = dataDir >>> aColl01.address = 'topics' Directory Collection Provider ----------------------------- The DirectoryCollectionProvider collects files from a directory in the file system. The parameters (directory paths) are provided by the calling object, the external collection itself. >>> from loops.integrator.collection import DirectoryCollectionProvider >>> dcp = DirectoryCollectionProvider() >>> sorted(dcp.collect(aColl01)) [('programming/BeautifulProgram.pdf', datetime.datetime(2005, 4, 7, 12, 36, 56)), ('programming/zope/zope3.txt', datetime.datetime(2007, 4, 12, 15, 16, 13))] If we provide a more selective pattern we get only part of the files: >>> aColl01.pattern = r'.*\.txt' >>> sorted(dcp.collect(aColl01)) [('programming/zope/zope3.txt', datetime.datetime(2007, 4, 12, 15, 16, 13))] Let's now create the corresponding resource objects. >>> aColl01.pattern = '' >>> addresses = [e[0] for e in dcp.collect(aColl01)] >>> res = list(dcp.createExtFileObjects(aColl01, addresses)) >>> len(sorted(r.__name__ for r in res)) 2 >>> xf1 = res[0] >>> xf1.__name__ u'programming_beautifulprogram.pdf' >>> xf1.title u'BeautifulProgram' >>> xf1.contentType 'application/pdf' >>> from loops.common import adapted >>> aXf1 = adapted(xf1) >>> aXf1.storageName 'fullpath' >>> aXf1.storageParams {'subdirectory': '...topics'} >>> for r in res: del resources[r.__name__] Working with the External Collection ------------------------------------ >>> component.provideUtility(DirectoryCollectionProvider()) >>> aColl01.update() >>> res = coll01.getResources() >>> len(res) 2 >>> sorted((r.__name__, r.title, r._storageName) for r in res) [(u'programming_beautifulprogram.pdf', u'BeautifulProgram', 'fullpath'), (u'programming_zope_zope3.txt', u'zope3', 'fullpath')] If one of the referenced objects is not found any more it will be deleted. So if we change one of the collection parameters probably all old resources will be removed and newly created. >>> import os >>> aColl01.address = os.path.join('topics', 'programming') >>> aColl01.update() >>> res = sorted(coll01.getResources(), key=lambda x: getName(x)) >>> len(res) 2 >>> xf1 = res[0] >>> aXf1 = adapted(xf1) >>> aXf1.storageParams {'subdirectory': '...programming'} Fin de partie ============= >>> placefulTearDown()