loops.integrator: integrating filesystem directories working
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1691 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
9133b0fb52
commit
ea09e0d836
5 changed files with 84 additions and 16 deletions
12
common.py
12
common.py
|
@ -31,10 +31,22 @@ from zope.interface import implements
|
|||
from zope.cachedescriptors.property import Lazy
|
||||
|
||||
from cybertools.storage.interfaces import IStorageInfo
|
||||
from cybertools.typology.interfaces import IType
|
||||
from loops.interfaces import ILoopsObject, ILoopsContained, IConcept, IResource
|
||||
from loops.interfaces import IResourceAdapter
|
||||
|
||||
|
||||
def adapted(obj):
|
||||
t = IType(obj, None)
|
||||
if t is not None:
|
||||
ti = t.typeInterface
|
||||
if ti is not None:
|
||||
adapted = ti(obj, None)
|
||||
if adapted is not None:
|
||||
return adapted
|
||||
return obj
|
||||
|
||||
|
||||
# type interface adapters
|
||||
|
||||
class AdapterBase(object):
|
||||
|
|
|
@ -86,9 +86,17 @@ Let's now create the corresponding resource objects.
|
|||
u'programming_beautifulprogram.pdf'
|
||||
>>> xf1.title
|
||||
u'BeautifulProgram'
|
||||
>>> xf1.contentType
|
||||
'application/pdf'
|
||||
|
||||
>>> for r in res:
|
||||
... del resources[r.__name__]
|
||||
>>> 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
|
||||
------------------------------------
|
||||
|
@ -102,7 +110,20 @@ Working with the External Collection
|
|||
[(u'programming_beautifulprogram.pdf', u'BeautifulProgram', 'fullpath'),
|
||||
(u'programming_zope_zope3.txt', u'zope3', 'fullpath')]
|
||||
|
||||
To do: Check storage parameters.
|
||||
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
|
||||
|
|
|
@ -26,19 +26,20 @@ $Id$
|
|||
from datetime import datetime
|
||||
import os, re, stat
|
||||
|
||||
from zope import component
|
||||
from zope.lifecycleevent import ObjectModifiedEvent
|
||||
from zope.event import notify
|
||||
from zope.app.container.interfaces import INameChooser
|
||||
from zope.component import adapts
|
||||
from zope.interface import implements, Attribute
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
from zope import component
|
||||
from zope.component import adapts
|
||||
from zope.contenttype import guess_content_type
|
||||
from zope.event import notify
|
||||
from zope.lifecycleevent import ObjectModifiedEvent
|
||||
from zope.interface import implements, Attribute
|
||||
from zope.schema.interfaces import IField
|
||||
from zope.traversing.api import getName, getParent
|
||||
|
||||
from cybertools.text import mimetypes
|
||||
from cybertools.typology.interfaces import IType
|
||||
from loops.common import AdapterBase
|
||||
from loops.common import AdapterBase, adapted
|
||||
from loops.interfaces import IResource, IConcept
|
||||
from loops.integrator.interfaces import IExternalCollection
|
||||
from loops.integrator.interfaces import IExternalCollectionProvider
|
||||
|
@ -63,12 +64,16 @@ class ExternalCollectionAdapter(AdapterBase):
|
|||
|
||||
def update(self):
|
||||
existing = self.context.getResources()
|
||||
old = dict((obj.externalAddress, obj) for obj in existing)
|
||||
old = dict((adapted(obj).externalAddress, obj) for obj in existing)
|
||||
new = []
|
||||
oldFound = []
|
||||
provider = component.getUtility(IExternalCollectionProvider,
|
||||
name=self.providerName or '')
|
||||
for addr, mdate in provider.collect(self):
|
||||
if addr in old:
|
||||
# may be it would be better to return a file's hash
|
||||
# for checking for changes...
|
||||
oldFound.append(addr)
|
||||
if mdate > self.lastUpdated:
|
||||
# force reindexing
|
||||
notify(ObjectModifiedEvent(old[addr]))
|
||||
|
@ -78,8 +83,23 @@ class ExternalCollectionAdapter(AdapterBase):
|
|||
newResources = provider.createExtFileObjects(self, new)
|
||||
for r in newResources:
|
||||
self.context.assignResource(r)
|
||||
for addr in old:
|
||||
if addr not in oldFound:
|
||||
# not part of the collection any more
|
||||
self.remove(old[addr])
|
||||
self.lastUpdated = datetime.today()
|
||||
|
||||
def clear(self):
|
||||
for obj in self.context.getResources():
|
||||
self.remove(obj)
|
||||
|
||||
def remove(self, obj):
|
||||
del self.resourceManager[getName(obj)]
|
||||
|
||||
@Lazy
|
||||
def resourceManager(self):
|
||||
return self.context.getLoopsRoot().getResourceManager()
|
||||
|
||||
|
||||
class DirectoryCollectionProvider(object):
|
||||
""" A utility that provides access to files in a directory.
|
||||
|
@ -95,8 +115,6 @@ class DirectoryCollectionProvider(object):
|
|||
del dirs[dirs.index('.svn')]
|
||||
for f in files:
|
||||
if pattern.match(f):
|
||||
# may be it would be better to return a file's hash
|
||||
# for checking for changes...
|
||||
mtime = os.stat(os.path.join(path, f))[stat.ST_MTIME]
|
||||
yield (os.path.join(path[len(directory)+1:], f),
|
||||
datetime.fromtimestamp(mtime))
|
||||
|
@ -115,7 +133,10 @@ class DirectoryCollectionProvider(object):
|
|||
resourceType=extFileType,
|
||||
externalAddress=addr,
|
||||
storageName='fullpath',
|
||||
storageParams=dict(subdirectory=directory))
|
||||
storageParams=dict(subdirectory=directory),
|
||||
contentType = guess_content_type(addr,
|
||||
default='application/octet-stream')[0]
|
||||
)
|
||||
yield obj
|
||||
|
||||
def getDirectory(self, client):
|
||||
|
|
|
@ -9,20 +9,23 @@ from zope.app.catalog.catalog import Catalog
|
|||
from zope.app.catalog.interfaces import ICatalog
|
||||
from zope.app.catalog.field import FieldIndex
|
||||
from zope.app.catalog.text import TextIndex
|
||||
from zope.app.container.interfaces import IObjectRemovedEvent
|
||||
|
||||
from cybertools.relation.tests import IntIdsStub
|
||||
from cybertools.relation.registry import RelationRegistry
|
||||
from cybertools.relation.interfaces import IRelationRegistry
|
||||
from cybertools.relation.interfaces import IRelation, IRelationRegistry
|
||||
from cybertools.relation.interfaces import IRelationInvalidatedEvent
|
||||
from cybertools.relation.registry import IndexableRelationAdapter
|
||||
from cybertools.relation.registry import invalidateRelations, removeRelation
|
||||
from cybertools.typology.interfaces import IType
|
||||
|
||||
from loops import Loops
|
||||
from loops import util
|
||||
from loops.common import NameChooser
|
||||
from loops.interfaces import IIndexAttributes, IDocument
|
||||
from loops.interfaces import ILoopsObject, IIndexAttributes, IDocument, IFile
|
||||
from loops.concept import Concept
|
||||
from loops.concept import IndexAttributes as ConceptIndexAttributes
|
||||
from loops.resource import Resource
|
||||
from loops.resource import Resource, FileAdapter
|
||||
from loops.resource import IndexAttributes as ResourceIndexAttributes
|
||||
from loops.setup import SetupManager, addObject
|
||||
from loops.type import LoopsType, ConceptType, ResourceType, TypeConcept
|
||||
|
@ -46,8 +49,14 @@ class TestSite(object):
|
|||
component.provideAdapter(ConceptType)
|
||||
component.provideAdapter(ResourceType, (IDocument,))
|
||||
component.provideAdapter(TypeConcept)
|
||||
component.provideAdapter(FileAdapter, provides=IFile)
|
||||
component.provideAdapter(NameChooser)
|
||||
|
||||
component.getSiteManager().registerHandler(invalidateRelations,
|
||||
(ILoopsObject, IObjectRemovedEvent))
|
||||
component.getSiteManager().registerHandler(removeRelation,
|
||||
(IRelation, IRelationInvalidatedEvent))
|
||||
|
||||
catalog = self.catalog = Catalog()
|
||||
component.provideUtility(catalog, ICatalog)
|
||||
catalog['loops_title'] = TextIndex('title', IIndexAttributes, True)
|
||||
|
|
|
@ -132,3 +132,8 @@ In addition it is possible to explicitly retrieve a certain version:
|
|||
>>> IVersionable(getVersion(d001v1_2, TestRequest(form=dict(version='1.1')))).versionId
|
||||
'1.1'
|
||||
|
||||
|
||||
Fin de partie
|
||||
=============
|
||||
|
||||
>>> placefulTearDown()
|
||||
|
|
Loading…
Add table
Reference in a new issue