From 9133b0fb52a3aec9f3225543b605b793d065f645 Mon Sep 17 00:00:00 2001 From: helmutm Date: Sat, 14 Apr 2007 21:40:02 +0000 Subject: [PATCH] loops.integrator: provide view for show and update external collections git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1690 fd906abe-77d9-0310-91a1-e0d9ade77398 --- browser/concept.py | 14 +++++++--- integrator/README.txt | 8 +++--- integrator/browser.py | 48 +++++++++++++++++++++++++++++++++ integrator/collection.py | 3 ++- integrator/collection_macros.pt | 11 ++++++++ integrator/configure.zcml | 11 ++++++++ integrator/testsetup.py | 7 +++-- resource.py | 3 +++ setup.py | 7 +++-- tests/setup.py | 7 ++--- 10 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 integrator/browser.py create mode 100644 integrator/collection_macros.pt diff --git a/browser/concept.py b/browser/concept.py index 982bce6..c17feaa 100644 --- a/browser/concept.py +++ b/browser/concept.py @@ -44,6 +44,7 @@ from zope.security.proxy import removeSecurityProxy from cybertools.typology.interfaces import IType, ITypeManager from loops.interfaces import IConcept +from loops.interfaces import ITypeConcept from loops.concept import Concept, ConceptTypeSourceList, PredicateSourceList from loops.browser.common import EditForm, BaseView, LoopsTerms from loops import util @@ -133,20 +134,25 @@ class ConceptView(BaseView): @Lazy def view(self): + context = self.context viewName = self.request.get('loops.viewName') or getattr(self, '_viewName', None) if not viewName: - ti = IType(self.context).typeInterface + ti = IType(context).typeInterface # TODO: check the interface (maybe for a base interface IViewProvider) # instead of the viewName attribute: - if ti and 'viewName' in ti: + if ti and ti != ITypeConcept and 'viewName' in ti: typeAdapter = ti(self.context) viewName = typeAdapter.viewName + if not viewName: + tp = IType(context).typeProvider + if tp: + viewName = ITypeConcept(tp).viewName if viewName: # ??? Would it make sense to use a somehow restricted interface # that should be provided by the view like IQuery? #viewInterface = getattr(typeAdapter, 'viewInterface', None) or IQuery - adapter = component.queryMultiAdapter((self.context, self.request), - interface.Interface, name=viewName) + adapter = component.queryMultiAdapter((context, self.request), + name=viewName) if adapter is not None: return adapter #elif type provides view: use this diff --git a/integrator/README.txt b/integrator/README.txt index 2614360..670e057 100644 --- a/integrator/README.txt +++ b/integrator/README.txt @@ -98,9 +98,11 @@ Working with the External Collection >>> res = coll01.getResources() >>> len(res) 2 - >>> sorted((r.__name__, r.title) for r in res) - [(u'programming_beautifulprogram.pdf', u'BeautifulProgram'), - (u'programming_zope_zope3.txt', u'zope3')] + >>> 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')] + +To do: Check storage parameters. Fin de partie diff --git a/integrator/browser.py b/integrator/browser.py new file mode 100644 index 0000000..626d694 --- /dev/null +++ b/integrator/browser.py @@ -0,0 +1,48 @@ +# +# Copyright (c) 2007 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 +# + +""" +View class(es) for intergrating external objects. + +$Id$ +""" + +from zope import interface, component +from zope.app.pagetemplate import ViewPageTemplateFile +from zope.cachedescriptors.property import Lazy + +from cybertools.typology.interfaces import IType +from loops.browser.concept import ConceptView + + +class ExternalCollectionView(ConceptView): + + macro_template = ViewPageTemplateFile('collection_macros.pt') + + @property + def macro(self): + return self.macro_template.macros['render_collection'] + + def update(self): + if 'update' in self.request.form: + ti = IType(self.context).typeInterface + if ti is not None: + adapted = ti(self.context) + adapted.update() + return True + diff --git a/integrator/collection.py b/integrator/collection.py index 870462f..529236f 100644 --- a/integrator/collection.py +++ b/integrator/collection.py @@ -70,6 +70,7 @@ class ExternalCollectionAdapter(AdapterBase): for addr, mdate in provider.collect(self): if addr in old: if mdate > self.lastUpdated: + # force reindexing notify(ObjectModifiedEvent(old[addr])) else: new.append(addr) @@ -113,7 +114,7 @@ class DirectoryCollectionProvider(object): title=title, resourceType=extFileType, externalAddress=addr, - storage='fullpath', + storageName='fullpath', storageParams=dict(subdirectory=directory)) yield obj diff --git a/integrator/collection_macros.pt b/integrator/collection_macros.pt new file mode 100644 index 0000000..e824484 --- /dev/null +++ b/integrator/collection_macros.pt @@ -0,0 +1,11 @@ + + + + +
+ +
+ +
+ diff --git a/integrator/configure.zcml b/integrator/configure.zcml index ad7799a..3f40343 100644 --- a/integrator/configure.zcml +++ b/integrator/configure.zcml @@ -19,4 +19,15 @@ + + + + diff --git a/integrator/testsetup.py b/integrator/testsetup.py index 1b491cd..83ab22f 100644 --- a/integrator/testsetup.py +++ b/integrator/testsetup.py @@ -8,9 +8,9 @@ import os from zope import component from loops import util -from loops.interfaces import IExternalFile +from loops.interfaces import IFile, IExternalFile from loops.concept import Concept -from loops.resource import Resource +from loops.resource import Resource, FileAdapter, ExternalFileAdapter from loops.integrator.interfaces import IExternalCollection from loops.knowledge.setup import SetupManager as KnowledgeSetupManager from loops.setup import SetupManager, addAndConfigureObject @@ -28,6 +28,9 @@ class TestSite(BaseTestSite): component.provideAdapter(KnowledgeSetupManager, name='knowledge') concepts, resources, views = self.baseSetup() + component.provideAdapter(FileAdapter, provides=IFile) + component.provideAdapter(ExternalFileAdapter, provides=IExternalFile) + tType = concepts.getTypeConcept() tExtFile = addAndConfigureObject(concepts, Concept, 'extfile', title=u'External File', conceptType=tType, diff --git a/resource.py b/resource.py index 8ee01db..d87f6a4 100644 --- a/resource.py +++ b/resource.py @@ -305,6 +305,9 @@ class ExternalFileAdapter(FileAdapter): implements(IExternalFile) + _adapterAttributes = (FileAdapter._adapterAttributes + + ('storageParams', 'externalAddress')) + def getStorageParams(self): params = getattr(self.context, '_storageParams', None) if params is not None: diff --git a/setup.py b/setup.py index 35d894d..b2f1cc7 100644 --- a/setup.py +++ b/setup.py @@ -114,9 +114,12 @@ def addAndConfigureObject(container, class_, name, **kw): basicKw = dict([(k, kw[k]) for k in kw if k in basicAttributes]) obj = addObject(container, class_, name, **basicKw) ti = IType(obj).typeInterface - adapted = ti is not None and ti(obj) or obj + if ti is not None: + adapted = ti(obj) + else: + adapted = obj adapterAttributes = [k for k in kw if k not in basicAttributes] for attr in adapterAttributes: - setattr(obj, attr, kw[attr]) + setattr(adapted, attr, kw[attr]) notify(ObjectModifiedEvent(obj)) return obj diff --git a/tests/setup.py b/tests/setup.py index 7e79cf9..97401f8 100644 --- a/tests/setup.py +++ b/tests/setup.py @@ -19,13 +19,13 @@ from cybertools.typology.interfaces import IType from loops import Loops from loops import util from loops.common import NameChooser -from loops.interfaces import IIndexAttributes +from loops.interfaces import IIndexAttributes, IDocument from loops.concept import Concept from loops.concept import IndexAttributes as ConceptIndexAttributes from loops.resource import Resource from loops.resource import IndexAttributes as ResourceIndexAttributes from loops.setup import SetupManager, addObject -from loops.type import ConceptType, ResourceType, TypeConcept +from loops.type import LoopsType, ConceptType, ResourceType, TypeConcept class TestSite(object): @@ -42,8 +42,9 @@ class TestSite(object): component.provideUtility(relations, IRelationRegistry) component.provideAdapter(IndexableRelationAdapter) + component.provideAdapter(LoopsType) component.provideAdapter(ConceptType) - component.provideAdapter(ResourceType) + component.provideAdapter(ResourceType, (IDocument,)) component.provideAdapter(TypeConcept) component.provideAdapter(NameChooser)