diff --git a/README.txt b/README.txt index 3041d14..3ed2701 100755 --- a/README.txt +++ b/README.txt @@ -20,7 +20,6 @@ with lower-level aspects like type or state management. >>> from zope import component >>> from zope.app import zapi - >>> from zope.app.tests import ztapi >>> from zope.interface import Interface >>> from zope.publisher.browser import TestRequest @@ -54,16 +53,12 @@ Now we want to relate the second concept to the first one. In order to do this we first have to provide a relation registry. For testing we use a simple dummy implementation. - >>> from zope.app.intid.interfaces import IIntIds >>> from cybertools.relation.tests import IntIdsStub - >>> from zope.app.testing import ztapi - >>> ztapi.provideUtility(IIntIds, IntIdsStub()) + >>> component.provideUtility(IntIdsStub()) >>> from cybertools.relation.interfaces import IRelationRegistry >>> from cybertools.relation.registry import DummyRelationRegistry - >>> ztapi.provideUtility(IRelationRegistry, DummyRelationRegistry()) + >>> component.provideUtility(DummyRelationRegistry()) >>> from cybertools.relation.registry import RelationRegistry - >>> #ztapi.provideUtility(IRelationRegistry, RelationRegistry()) - >>> #zapi.getUtility(IRelationRegistry).setupIndexes() As relationships are based on predicates that are themselves concepts we also need a default predicate concept; the default name for this is @@ -124,7 +119,7 @@ type manager. >>> from cybertools.typology.interfaces import ITypeManager >>> from loops.interfaces import ILoopsObject >>> from loops.type import LoopsTypeManager, LoopsType - >>> ztapi.provideAdapter(ILoopsObject, ITypeManager, LoopsTypeManager) + >>> component.provideAdapter(LoopsTypeManager, (ILoopsObject,), ITypeManager) >>> from loops.concept import ConceptTypeSourceList >>> types = ConceptTypeSourceList(cc1) @@ -205,8 +200,7 @@ types and predicates. >>> from loops.browser.common import LoopsTerms >>> from zope.app.form.browser.interfaces import ITerms >>> from zope.schema.interfaces import IIterableSource - >>> ztapi.provideAdapter(IIterableSource, ITerms, LoopsTerms, - ... with=(IBrowserRequest,)) + >>> component.provideAdapter(LoopsTerms, (IIterableSource, IBrowserRequest), ITerms) >>> sorted((t.title, t.token) for t in view.conceptTypes()) [(u'Topic', '.loops/concepts/topic'), (u'Type', '.loops/concepts/type'), @@ -421,8 +415,8 @@ out - this is usually done through ZCML.) >>> from loops.util import removeTargetRelation >>> from loops.interfaces import ITargetRelation >>> from cybertools.relation.interfaces import IRelationInvalidatedEvent - >>> ztapi.subscribe([ITargetRelation, IRelationInvalidatedEvent], None, - ... removeTargetRelation) + >>> component.getSiteManager().registerHandler(removeTargetRelation, + ... (ITargetRelation, IRelationInvalidatedEvent)) >>> m111.target = cc1 >>> m111.target is cc1 @@ -493,10 +487,8 @@ view; these views we have to provide as multi-adapters: >>> from loops.browser.node import ConfigureView >>> from loops.browser.resource import DocumentView, ResourceView - >>> ztapi.provideAdapter(IDocument, Interface, DocumentView, - ... with=(IBrowserRequest,)) - >>> ztapi.provideAdapter(IResource, Interface, ResourceView, - ... with=(IBrowserRequest,)) + >>> component.provideAdapter(DocumentView, (IDocument, IBrowserRequest), Interface) + >>> component.provideAdapter(ResourceView, (IResource, IBrowserRequest), Interface) >>> form = {'action': 'create', 'create.title': 'New Resource', ... 'create.type': 'loops.resource.MediaAsset',} @@ -538,11 +530,10 @@ view for rendering.) >>> from zope.component.interfaces import IFactory >>> from zope.app.renderer import rest - >>> ztapi.provideUtility(IFactory, rest.ReStructuredTextSourceFactory, - ... 'zope.source.rest') - >>> ztapi.provideAdapter(rest.IReStructuredTextSource, Interface, - ... rest.ReStructuredTextToHTMLRenderer, - ... with=(IBrowserRequest,)) + >>> component.provideUtility(rest.ReStructuredTextSourceFactory, IFactory, + ... 'zope.source.rest') + >>> component.provideAdapter(rest.ReStructuredTextToHTMLRenderer, + ... (rest.IReStructuredTextSource, IBrowserRequest), Interface) >>> m112.target = doc1 @@ -557,18 +548,6 @@ view for rendering.) >>> view.renderTarget() u'

Test data

\n

Another paragraph

\n' -It is possible to edit a target's attributes directly in an -edit form provided by the node: - - >>> from loops.target import DocumentProxy, MediaAssetProxy - >>> ztapi.provideAdapter(INode, IDocumentView, DocumentProxy) - >>> ztapi.provideAdapter(INode, IMediaAssetView, MediaAssetProxy) - - >>> proxy = zapi.getAdapter(m111, IDocumentView) - >>> proxy.title = u'Set via proxy' - >>> resources['doc1'].title - u'Set via proxy' - If the target object is removed from its container all references to it are removed as well. (To make this work we have to handle the IObjectRemovedEvent; this is usually done via ZCML in the @@ -577,14 +556,26 @@ cybertools.relation package.) >>> from zope.app.container.interfaces import IObjectRemovedEvent >>> from zope.interface import Interface >>> from cybertools.relation.registry import invalidateRelations - >>> ztapi.subscribe([Interface, IObjectRemovedEvent], None, - ... invalidateRelations) + >>> component.getSiteManager().registerHandler(invalidateRelations, + ... (Interface, IObjectRemovedEvent)) >>> del resources['doc1'] >>> m111.target >>> IMediaAssetView.providedBy(m111) False +Views Related to Virtual Targets +-------------------------------- + +From a node usually any object in the concept or resource space can +be accessed as a `virtual target`. This is done by putting ".targetNNN" +at the end of the URL, with NNN being the unique id of the concept +or resource. + + >>> from loops.view import NodeTraverser + >>> from zope.publisher.interfaces.browser import IBrowserPublisher + >>> component.provideAdapter(NodeTraverser, provides=IBrowserPublisher) + Ordering Nodes -------------- diff --git a/base.py b/base.py index babc7fc..b261276 100644 --- a/base.py +++ b/base.py @@ -23,8 +23,10 @@ $Id$ """ +from zope.app.container.btree import BTreeContainer from zope.app.folder.folder import Folder -from zope.app.traversing.api import getPath, traverse +from zope.app.folder.interfaces import IFolder +from zope.traversing.api import getPath, traverse from zope.interface import implements from loops.interfaces import ILoops @@ -33,9 +35,17 @@ loopsPrefix = '.loops' class Loops(Folder): +#class Loops(BTreeContainer): implements(ILoops) + def getSiteManager(self): + return self.__parent__.getSiteManager() + + @property + def _SampleContainer__data(self): + return self.data + _skinName = '' def getSkinName(self): return self._skinName def setSkinName(self, skinName): self._skinName = skinName diff --git a/browser/common.py b/browser/common.py index 2a1198d..eae5999 100644 --- a/browser/common.py +++ b/browser/common.py @@ -23,7 +23,7 @@ $Id$ """ from zope.app import zapi -from zope.app.dublincore.interfaces import IZopeDublinCore +from zope.dublincore.interfaces import IZopeDublinCore from zope.app.form.browser.interfaces import ITerms from zope.cachedescriptors.property import Lazy from zope.dottedname.resolve import resolve @@ -31,8 +31,9 @@ from zope.formlib import form from zope.formlib.form import FormFields from zope.formlib.namedtemplate import NamedTemplate from zope.interface import Interface, implements -from zope.app.publisher.browser import applySkin -from zope.publisher.interfaces.browser import ISkin +from zope.publisher.browser import applySkin +#from zope.publisher.interfaces.browser import ISkin +from zope.publisher.interfaces.browser import IBrowserSkinType from zope import schema from zope.schema.vocabulary import SimpleTerm from zope.security import canAccess, canWrite @@ -92,7 +93,7 @@ class BaseView(GenericView): def setSkin(self, skinName): skin = None if skinName and IView.providedBy(self.context): - skin = zapi.queryUtility(ISkin, skinName) + skin = zapi.queryUtility(IBrowserSkinType, skinName) if skin: applySkin(self.request, skin) self.skin = skin diff --git a/browser/concept.py b/browser/concept.py index 2a7c809..ee0be16 100644 --- a/browser/concept.py +++ b/browser/concept.py @@ -25,7 +25,7 @@ $Id$ from zope import interface, component, schema from zope.app import zapi from zope.app.catalog.interfaces import ICatalog -from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent +from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent from zope.app.container.contained import ObjectRemovedEvent from zope.app.form.browser.interfaces import ITerms from zope.app.form.interfaces import IDisplayWidget diff --git a/browser/configure.zcml b/browser/configure.zcml index c61e6bb..b7c477d 100644 --- a/browser/configure.zcml +++ b/browser/configure.zcml @@ -494,7 +494,7 @@ menu="zmi_views" title="Configure" /> - + />--> + + diff --git a/browser/form.py b/browser/form.py index 3f265b7..bf5e369 100644 --- a/browser/form.py +++ b/browser/form.py @@ -25,10 +25,12 @@ $Id$ from zope import component, interface, schema from zope.component import adapts from zope.event import notify -from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent +from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent from zope.app.container.interfaces import INameChooser from zope.app.container.contained import NameChooser +#from zope.app.content_types import guess_content_types +from zope.app.form.browser.textwidgets import FileWidget, TextAreaWidget from zope.app.pagetemplate import ViewPageTemplateFile from zope.cachedescriptors.property import Lazy from zope.formlib.form import Form, EditForm, FormFields @@ -49,6 +51,21 @@ from loops import util from loops.util import _ +# special widgets + +class UploadWidget(FileWidget): + + def _toFieldValue(self, input): + fn = getattr(input, 'filename', '') # zope.publisher.browser.FileUpload + self.request.form['filename'] = fn + if input: + self.request.form['_tempfilename'] = input.headers.get('_tempfilename') + # f = self.context + # f.extfiledata = tempfilename # provide for rename + # f.contentType = guess_content_types(fn) + return super(UploadWidget, self)._toFieldValue(input) + + # forms class ObjectForm(NodeView): @@ -84,6 +101,8 @@ class NoteWidgetController(object): widgetControllers = {INote: NoteWidgetController} +# specialWidgets = {(IFile, 'data'): UploadWidget} + class EditObjectForm(ObjectForm, EditForm): diff --git a/browser/form_macros.pt b/browser/form_macros.pt index 0df5ba3..f793287 100644 --- a/browser/form_macros.pt +++ b/browser/form_macros.pt @@ -1,3 +1,6 @@ + +
- + @@ -56,7 +56,7 @@ permission="zope.ManageContent" set_schema=".interfaces.ILoops" /> - + diff --git a/helpers.txt b/helpers.txt index 4ca04d5..c006d56 100755 --- a/helpers.txt +++ b/helpers.txt @@ -15,7 +15,6 @@ Let's first do some basic imports >>> from zope import interface, component >>> from zope.app import zapi - >>> from zope.app.tests import ztapi >>> from zope.interface import Interface >>> from zope.publisher.browser import TestRequest @@ -23,8 +22,7 @@ and provide a relation registry: >>> from cybertools.relation.interfaces import IRelationRegistry >>> from cybertools.relation.registry import DummyRelationRegistry - >>> from zope.app.testing import ztapi - >>> ztapi.provideUtility(IRelationRegistry, DummyRelationRegistry()) + >>> component.provideUtility(DummyRelationRegistry()) and care for some type adapter machinery: @@ -96,7 +94,7 @@ purpose: >>> from cybertools.typology.interfaces import IType >>> from loops.type import ConceptType - >>> ztapi.provideAdapter(IConcept, IType, ConceptType) + >>> component.provideAdapter(ConceptType) >>> cc1_type = IType(cc1) As we have not yet associated a type with one of our content objects we get @@ -182,7 +180,7 @@ Now let's have a look at resources. >>> from loops.interfaces import IResource, IDocument >>> from loops.type import ResourceType - >>> ztapi.provideAdapter(IDocument, IType, ResourceType) + >>> component.provideAdapter(ResourceType, (IDocument,), IType) >>> doc1_type = IType(doc1) >>> doc1_type.title @@ -231,7 +229,7 @@ get a type manager from all loops objects, always with the same context: >>> from cybertools.typology.interfaces import ITypeManager >>> from loops.interfaces import ILoopsObject >>> from loops.type import LoopsTypeManager - >>> ztapi.provideAdapter(ILoopsObject, ITypeManager, LoopsTypeManager) + >>> component.provideAdapter(LoopsTypeManager) >>> typeManager = ITypeManager(loopsRoot) >>> typeManager.context == ITypeManager(cc1).context == loopsRoot True @@ -366,8 +364,8 @@ view/multi-adapter with this name: Controlling presentation using view properties ---------------------------------------------- - >>> from zope.app.annotation.interfaces import IAttributeAnnotatable, IAnnotations - >>> from zope.app.annotation.attribute import AttributeAnnotations + >>> from zope.annotation.interfaces import IAttributeAnnotatable, IAnnotations + >>> from zope.annotation.attribute import AttributeAnnotations >>> from loops.interfaces import INode First we have to make sure we can use attribute annotations with our nodes, diff --git a/interfaces.py b/interfaces.py index 6b20e79..f406283 100644 --- a/interfaces.py +++ b/interfaces.py @@ -29,7 +29,7 @@ from zope.app.container.constraints import contains, containers from zope.app.container.interfaces import IContainer, IOrderedContainer from zope.app.file.interfaces import IImage as IBaseAsset from zope.app.folder.interfaces import IFolder -from zope.app.size.interfaces import ISized +from zope.size.interfaces import ISized from cybertools.relation.interfaces import IRelation import util diff --git a/organize/README.txt b/organize/README.txt index 9c742e0..e849f31 100644 --- a/organize/README.txt +++ b/organize/README.txt @@ -10,18 +10,18 @@ Let's do some basic set up >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown >>> site = placefulSetUp(True) - + >>> from zope import component, interface >>> from zope.app import zapi and setup a simple loops site with a concept manager and some concepts (with all the type machinery, what in real life is done via standard ZCML setup): - + >>> from cybertools.relation.interfaces import IRelationRegistry >>> from cybertools.relation.registry import DummyRelationRegistry >>> relations = DummyRelationRegistry() - >>> component.provideUtility(relations, IRelationRegistry) + >>> component.provideUtility(relations) >>> from cybertools.typology.interfaces import IType >>> from loops.interfaces import IConcept, ITypeConcept @@ -34,7 +34,7 @@ ZCML setup): >>> from loops.organize.setup import SetupManager >>> component.provideAdapter(SetupManager, (ILoops,), ISetupManager, ... name='organize') - + >>> from loops import Loops >>> loopsRoot = site['loops'] = Loops() >>> loopsId = relations.getUniqueIdForObject(loopsRoot) @@ -42,10 +42,10 @@ ZCML setup): >>> from loops.setup import SetupManager >>> setup = SetupManager(loopsRoot) >>> concepts, resources, views = setup.setup() - + >>> type = concepts['type'] >>> person = concepts['person'] - + >>> from loops.concept import Concept >>> johnC = concepts['john'] = Concept(u'John') >>> johnC.conceptType = person @@ -94,7 +94,7 @@ For testing, we first have to provide the needed utilities and settings >>> from zope.app.security.principalregistry import PrincipalRegistry >>> auth = PrincipalRegistry() >>> component.provideUtility(auth, IAuthentication) - + >>> from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility >>> from zope.app.principalannotation import PrincipalAnnotationUtility >>> principalAnnotations = PrincipalAnnotationUtility() @@ -112,7 +112,7 @@ Change a userId assignment: >>> principal = auth.definePrincipal('users.johnny', u'Johnny', login='johnny') >>> john.userId = 'users.johnny' - + >>> annotations = principalAnnotations.getAnnotationsById('users.johnny') >>> annotations[ANNOTATION_KEY][loopsId] == johnC True @@ -174,19 +174,14 @@ with a principal folder: >>> from zope.app.appsetup.bootstrap import ensureUtility >>> from zope.app.authentication.authentication import PluggableAuthentication >>> ensureUtility(site, IAuthentication, '', PluggableAuthentication, - ... copy_to_zlog=False) - '' + ... copy_to_zlog=False, asObject=True) + <...PluggableAuthentication...> >>> pau = component.getUtility(IAuthentication, context=site) - >>> from zope.app.component.site import UtilityRegistration >>> from zope.app.authentication.principalfolder import PrincipalFolder >>> from zope.app.authentication.interfaces import IAuthenticatorPlugin >>> pFolder = PrincipalFolder('loops.') >>> pau['loops'] = pFolder - >>> reg = UtilityRegistration('loops', IAuthenticatorPlugin, pFolder) - >>> pau.registrationManager.addRegistration(reg) - 'UtilityRegistration' - >>> reg.status = u'Active' >>> pau.authenticatorPlugins = ('loops',) In addition, we have to create at least one node in the view space @@ -205,7 +200,7 @@ sure that a principal object can be served by a corresponding factory): >>> from zope.app.authentication.principalfolder import FoundPrincipalFactory >>> component.provideAdapter(FoundPrincipalFactory) - + >>> data = {'loginName': u'newuser', ... 'password': u'quack', ... 'passwordConfirm': u'quack', diff --git a/organize/member.py b/organize/member.py index 7c3e9ed..121b88a 100644 --- a/organize/member.py +++ b/organize/member.py @@ -29,7 +29,7 @@ from zope.interface import implements from zope.app.authentication.interfaces import IPluggableAuthentication from zope.app.authentication.interfaces import IAuthenticatorPlugin from zope.app.authentication.principalfolder import InternalPrincipal -from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent +from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent from zope.app.security.interfaces import IAuthentication from zope.event import notify from zope.i18nmessageid import MessageFactory diff --git a/organize/tests.py b/organize/tests.py index 8a4e5b5..a4759a2 100755 --- a/organize/tests.py +++ b/organize/tests.py @@ -9,7 +9,7 @@ from loops.organize.party import Person class Test(unittest.TestCase): "Basic tests for the organize sub-package." - def testSomethin(self): + def testSomething(self): pass diff --git a/organize/util.py b/organize/util.py index e3890e3..70a90cc 100644 --- a/organize/util.py +++ b/organize/util.py @@ -39,6 +39,9 @@ def getPrincipalFolder(context=None): if not authPluginId in pau.authenticatorPlugins: raise ValueError(u'There is no loops authenticator ' 'plugin available.') - return component.queryUtility(IAuthenticatorPlugin, authPluginId, - context=pau) + #return component.queryUtility(IAuthenticatorPlugin, authPluginId, + # context=pau) + for name, plugin in pau.getAuthenticatorPlugins(): + if name == authPluginId: + return plugin diff --git a/query.py b/query.py index f363810..0155ccb 100644 --- a/query.py +++ b/query.py @@ -24,7 +24,7 @@ $Id$ from zope import schema, component from zope.interface import Interface, Attribute, implements -from zope.app import traversing +from zope import traversing from zope.app.catalog.interfaces import ICatalog from zope.cachedescriptors.property import Lazy diff --git a/resource.py b/resource.py index f186d43..4e90f98 100644 --- a/resource.py +++ b/resource.py @@ -28,8 +28,8 @@ from zope.app.container.btree import BTreeContainer from zope.app.container.contained import Contained from zope.app.file.image import Image from zope.app.file.interfaces import IFile -from zope.app.filerepresentation.interfaces import IReadFile, IWriteFile -from zope.app.size.interfaces import ISized +from zope.filerepresentation.interfaces import IReadFile, IWriteFile +from zope.size.interfaces import ISized from zope.cachedescriptors.property import Lazy from zope.component import adapts from zope.i18nmessageid import MessageFactory @@ -38,7 +38,7 @@ from zope import schema from persistent import Persistent from cStringIO import StringIO -from zope.app.event.objectevent import ObjectModifiedEvent, Attributes +from zope.lifecycleevent import ObjectModifiedEvent, Attributes from zope.event import notify from cybertools.relation.registry import getRelations @@ -285,6 +285,7 @@ class DocumentWriteFileAdapter(object): self.context = context def write(self, data): + # TODO: use typeInterface... ITextDocument(self.context).data = unicode(data.replace('\r', ''), 'UTF-8') notify(ObjectModifiedEvent(self.context, Attributes(IDocument, 'data'))) diff --git a/search/browser.py b/search/browser.py index 4630820..a86d682 100644 --- a/search/browser.py +++ b/search/browser.py @@ -24,7 +24,7 @@ $Id$ """ from zope import interface, component -from zope.app import traversing +from zope import traversing from zope.app.pagetemplate import ViewPageTemplateFile from zope.cachedescriptors.property import Lazy from zope.formlib.namedtemplate import NamedTemplate, NamedTemplateImplementation diff --git a/setup.py b/setup.py index 50fdf24..fb1ff08 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ Automatic setup of a loops site. $Id$ """ -from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent +from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent from zope.event import notify from zope import component from zope.component import adapts @@ -67,7 +67,7 @@ class SetupManager(object): resources = self.addObject(loopsRoot, ResourceManager, 'resources') views = self.addObject(loopsRoot, ViewManager, 'views') return concepts, resources, views - + def setupCoreConcepts(self, conceptManager): typeConcept = self.addObject(conceptManager, Concept, 'type', title=u'Type') hasType = self.addObject(conceptManager, Concept, 'hasType', title=u'has Type') @@ -75,7 +75,7 @@ class SetupManager(object): standard = self.addObject(conceptManager, Concept, 'standard', title=u'subobject') file = self.addObject(conceptManager, Concept, 'file', title=u'File') image = self.addObject(conceptManager, Concept, 'image', title=u'Image') - textdocument = self.addObject(conceptManager, Concept, + textdocument = self.addObject(conceptManager, Concept, 'textdocument', title=u'Text Document') for c in (typeConcept, file, image, textdocument, predicate): c.conceptType = typeConcept diff --git a/view.py b/view.py index a99d2cd..a4c34b3 100644 --- a/view.py +++ b/view.py @@ -22,6 +22,7 @@ Definition of the View and related classses. $Id$ """ +from zope import component from zope.app import zapi from zope.app.container.btree import BTreeContainer from zope.app.container.contained import Contained @@ -185,9 +186,19 @@ class NodeTraverser(ItemTraverser): if name == '.loops': return self.context.getLoopsRoot() if name.startswith('.target'): + traversalStack = request._traversal_stack + while traversalStack and traversalStack[0].startswith('.target'): + # skip obsolete target references in the url + name = traversalStack.pop(0) + traversedNames = request._traversed_names + if traversedNames: + lastTraversed = traversedNames[-1] + if lastTraversed.startswith('.target') and lastTraversed != name: + # let tag show the current object + traversedNames[-1] = name if len(name) > len('.target'): uid = int(name[len('.target'):]) - target = zapi.getUtility(IIntIds).getObject(uid) + target = component.getUtility(IIntIds).getObject(uid) else: target = self.context.target if target is not None: diff --git a/xmlrpc/common.py b/xmlrpc/common.py index cd571aa..6421f4e 100644 --- a/xmlrpc/common.py +++ b/xmlrpc/common.py @@ -24,10 +24,10 @@ $Id$ from zope.interface import implements from zope.event import notify -from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent +from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent from zope.app.publisher.xmlrpc import XMLRPCView from zope.app.publisher.xmlrpc import MethodPublisher -from zope.app.traversing.api import getName +from zope.traversing.api import getName from zope.security.proxy import removeSecurityProxy from zope.cachedescriptors.property import Lazy