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 zope.cachedescriptors.property import Lazy
|
||||||
|
|
||||||
from cybertools.storage.interfaces import IStorageInfo
|
from cybertools.storage.interfaces import IStorageInfo
|
||||||
|
from cybertools.typology.interfaces import IType
|
||||||
from loops.interfaces import ILoopsObject, ILoopsContained, IConcept, IResource
|
from loops.interfaces import ILoopsObject, ILoopsContained, IConcept, IResource
|
||||||
from loops.interfaces import IResourceAdapter
|
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
|
# type interface adapters
|
||||||
|
|
||||||
class AdapterBase(object):
|
class AdapterBase(object):
|
||||||
|
|
|
@ -86,9 +86,17 @@ Let's now create the corresponding resource objects.
|
||||||
u'programming_beautifulprogram.pdf'
|
u'programming_beautifulprogram.pdf'
|
||||||
>>> xf1.title
|
>>> xf1.title
|
||||||
u'BeautifulProgram'
|
u'BeautifulProgram'
|
||||||
|
>>> xf1.contentType
|
||||||
|
'application/pdf'
|
||||||
|
|
||||||
>>> for r in res:
|
>>> from loops.common import adapted
|
||||||
... del resources[r.__name__]
|
>>> aXf1 = adapted(xf1)
|
||||||
|
>>> aXf1.storageName
|
||||||
|
'fullpath'
|
||||||
|
>>> aXf1.storageParams
|
||||||
|
{'subdirectory': '...topics'}
|
||||||
|
|
||||||
|
>>> for r in res: del resources[r.__name__]
|
||||||
|
|
||||||
Working with the External Collection
|
Working with the External Collection
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
@ -102,7 +110,20 @@ Working with the External Collection
|
||||||
[(u'programming_beautifulprogram.pdf', u'BeautifulProgram', 'fullpath'),
|
[(u'programming_beautifulprogram.pdf', u'BeautifulProgram', 'fullpath'),
|
||||||
(u'programming_zope_zope3.txt', u'zope3', '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
|
Fin de partie
|
||||||
|
|
|
@ -26,19 +26,20 @@ $Id$
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import os, re, stat
|
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.app.container.interfaces import INameChooser
|
||||||
from zope.component import adapts
|
|
||||||
from zope.interface import implements, Attribute
|
|
||||||
from zope.cachedescriptors.property import Lazy
|
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.schema.interfaces import IField
|
||||||
from zope.traversing.api import getName, getParent
|
from zope.traversing.api import getName, getParent
|
||||||
|
|
||||||
from cybertools.text import mimetypes
|
from cybertools.text import mimetypes
|
||||||
from cybertools.typology.interfaces import IType
|
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.interfaces import IResource, IConcept
|
||||||
from loops.integrator.interfaces import IExternalCollection
|
from loops.integrator.interfaces import IExternalCollection
|
||||||
from loops.integrator.interfaces import IExternalCollectionProvider
|
from loops.integrator.interfaces import IExternalCollectionProvider
|
||||||
|
@ -63,12 +64,16 @@ class ExternalCollectionAdapter(AdapterBase):
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
existing = self.context.getResources()
|
existing = self.context.getResources()
|
||||||
old = dict((obj.externalAddress, obj) for obj in existing)
|
old = dict((adapted(obj).externalAddress, obj) for obj in existing)
|
||||||
new = []
|
new = []
|
||||||
|
oldFound = []
|
||||||
provider = component.getUtility(IExternalCollectionProvider,
|
provider = component.getUtility(IExternalCollectionProvider,
|
||||||
name=self.providerName or '')
|
name=self.providerName or '')
|
||||||
for addr, mdate in provider.collect(self):
|
for addr, mdate in provider.collect(self):
|
||||||
if addr in old:
|
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:
|
if mdate > self.lastUpdated:
|
||||||
# force reindexing
|
# force reindexing
|
||||||
notify(ObjectModifiedEvent(old[addr]))
|
notify(ObjectModifiedEvent(old[addr]))
|
||||||
|
@ -78,8 +83,23 @@ class ExternalCollectionAdapter(AdapterBase):
|
||||||
newResources = provider.createExtFileObjects(self, new)
|
newResources = provider.createExtFileObjects(self, new)
|
||||||
for r in newResources:
|
for r in newResources:
|
||||||
self.context.assignResource(r)
|
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()
|
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):
|
class DirectoryCollectionProvider(object):
|
||||||
""" A utility that provides access to files in a directory.
|
""" A utility that provides access to files in a directory.
|
||||||
|
@ -95,8 +115,6 @@ class DirectoryCollectionProvider(object):
|
||||||
del dirs[dirs.index('.svn')]
|
del dirs[dirs.index('.svn')]
|
||||||
for f in files:
|
for f in files:
|
||||||
if pattern.match(f):
|
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]
|
mtime = os.stat(os.path.join(path, f))[stat.ST_MTIME]
|
||||||
yield (os.path.join(path[len(directory)+1:], f),
|
yield (os.path.join(path[len(directory)+1:], f),
|
||||||
datetime.fromtimestamp(mtime))
|
datetime.fromtimestamp(mtime))
|
||||||
|
@ -115,7 +133,10 @@ class DirectoryCollectionProvider(object):
|
||||||
resourceType=extFileType,
|
resourceType=extFileType,
|
||||||
externalAddress=addr,
|
externalAddress=addr,
|
||||||
storageName='fullpath',
|
storageName='fullpath',
|
||||||
storageParams=dict(subdirectory=directory))
|
storageParams=dict(subdirectory=directory),
|
||||||
|
contentType = guess_content_type(addr,
|
||||||
|
default='application/octet-stream')[0]
|
||||||
|
)
|
||||||
yield obj
|
yield obj
|
||||||
|
|
||||||
def getDirectory(self, client):
|
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.interfaces import ICatalog
|
||||||
from zope.app.catalog.field import FieldIndex
|
from zope.app.catalog.field import FieldIndex
|
||||||
from zope.app.catalog.text import TextIndex
|
from zope.app.catalog.text import TextIndex
|
||||||
|
from zope.app.container.interfaces import IObjectRemovedEvent
|
||||||
|
|
||||||
from cybertools.relation.tests import IntIdsStub
|
from cybertools.relation.tests import IntIdsStub
|
||||||
from cybertools.relation.registry import RelationRegistry
|
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 IndexableRelationAdapter
|
||||||
|
from cybertools.relation.registry import invalidateRelations, removeRelation
|
||||||
from cybertools.typology.interfaces import IType
|
from cybertools.typology.interfaces import IType
|
||||||
|
|
||||||
from loops import Loops
|
from loops import Loops
|
||||||
from loops import util
|
from loops import util
|
||||||
from loops.common import NameChooser
|
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 Concept
|
||||||
from loops.concept import IndexAttributes as ConceptIndexAttributes
|
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.resource import IndexAttributes as ResourceIndexAttributes
|
||||||
from loops.setup import SetupManager, addObject
|
from loops.setup import SetupManager, addObject
|
||||||
from loops.type import LoopsType, ConceptType, ResourceType, TypeConcept
|
from loops.type import LoopsType, ConceptType, ResourceType, TypeConcept
|
||||||
|
@ -46,8 +49,14 @@ class TestSite(object):
|
||||||
component.provideAdapter(ConceptType)
|
component.provideAdapter(ConceptType)
|
||||||
component.provideAdapter(ResourceType, (IDocument,))
|
component.provideAdapter(ResourceType, (IDocument,))
|
||||||
component.provideAdapter(TypeConcept)
|
component.provideAdapter(TypeConcept)
|
||||||
|
component.provideAdapter(FileAdapter, provides=IFile)
|
||||||
component.provideAdapter(NameChooser)
|
component.provideAdapter(NameChooser)
|
||||||
|
|
||||||
|
component.getSiteManager().registerHandler(invalidateRelations,
|
||||||
|
(ILoopsObject, IObjectRemovedEvent))
|
||||||
|
component.getSiteManager().registerHandler(removeRelation,
|
||||||
|
(IRelation, IRelationInvalidatedEvent))
|
||||||
|
|
||||||
catalog = self.catalog = Catalog()
|
catalog = self.catalog = Catalog()
|
||||||
component.provideUtility(catalog, ICatalog)
|
component.provideUtility(catalog, ICatalog)
|
||||||
catalog['loops_title'] = TextIndex('title', IIndexAttributes, True)
|
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
|
>>> IVersionable(getVersion(d001v1_2, TestRequest(form=dict(version='1.1')))).versionId
|
||||||
'1.1'
|
'1.1'
|
||||||
|
|
||||||
|
|
||||||
|
Fin de partie
|
||||||
|
=============
|
||||||
|
|
||||||
|
>>> placefulTearDown()
|
||||||
|
|
Loading…
Add table
Reference in a new issue