[Zope3-checkins] CVS: Zope3/src/zope/app/container - configure.zcml:1.11 zopecontainer.py:1.19
Steve Alexander
steve@cat-box.net
Wed, 4 Jun 2003 10:58:27 -0400
Update of /cvs-repository/Zope3/src/zope/app/container
In directory cvs.zope.org:/tmp/cvs-serv19568/src/zope/app/container
Modified Files:
configure.zcml zopecontainer.py
Log Message:
Installed and registered ZopeContainerDecorator.
For new code, it is now unnecessary to adapt a context-wrapped container
to ZopeContainerAdapter. The context-wrapper will do all the correct
wrapping and unwrapping, and will send the correct events.
Existing calls to getAdapter(container, IZopeContainer) are harmless, as
a context-wrapped container provides IZopeContainer. So, the getAdapter
call will simply return the already-wrapped container.
I'll be changing existing code to avoid using ZopeContainerAdapter.
=== Zope3/src/zope/app/container/configure.zcml 1.10 => 1.11 ===
--- Zope3/src/zope/app/container/configure.zcml:1.10 Mon Mar 31 09:48:40 2003
+++ Zope3/src/zope/app/container/configure.zcml Wed Jun 4 10:57:56 2003
@@ -5,79 +5,88 @@
xmlns:event="http://namespaces.zope.org/event"
>
- <adapter
+ <adapter
provides="zope.app.interfaces.container.find.IFind"
for="zope.app.interfaces.container.IReadContainer"
- permission="zope.ManageContent"
- factory="zope.app.container.find.FindAdapter"
+ permission="zope.ManageContent"
+ factory="zope.app.container.find.FindAdapter"
/>
- <adapter
+ <adapter
for="zope.app.interfaces.container.IReadContainer"
provides="zope.app.interfaces.file.IReadDirectory"
factory=".directory.noop"
/>
- <adapter
+ <adapter
for="zope.app.interfaces.container.IWriteContainer"
provides="zope.app.interfaces.file.IWriteDirectory"
factory=".directory.noop"
/>
- <adapter factory="zope.app.container.traversal.ContainerTraversable"
- provides="zope.app.interfaces.traversing.ITraversable"
- for="zope.app.interfaces.container.IReadContainer"
- />
-
- <adapter factory="zope.app.container.zopecontainer.ZopeContainerAdapter"
- provides="zope.app.interfaces.container.IZopeContainer"
- for="zope.app.interfaces.container.IContainer"
- />
-
- <adapter factory="zope.app.container.size.ContainerSized"
- provides="zope.app.interfaces.size.ISized"
- for="zope.app.interfaces.container.IContainer"
- />
+ <adapter
+ factory="zope.app.container.traversal.ContainerTraversable"
+ provides="zope.app.interfaces.traversing.ITraversable"
+ for="zope.app.interfaces.container.IReadContainer"
+ />
- <adapter
+ <adapter
+ factory="zope.app.container.zopecontainer.ZopeContainerAdapter"
+ provides="zope.app.interfaces.container.IZopeContainer"
+ for="zope.app.interfaces.container.IContainer"
+ />
+
+ <adapter
+ factory="zope.app.container.zopecontainer.ZopeContainerDecorator"
+ provides="zope.app.interfaces.context.IZopeContextWrapper"
+ for="zope.app.interfaces.container.IContainer"
+ />
+
+ <adapter
+ factory="zope.app.container.size.ContainerSized"
+ provides="zope.app.interfaces.size.ISized"
+ for="zope.app.interfaces.container.IContainer"
+ />
+
+ <adapter
provides="zope.app.interfaces.container.ICopySource"
for="zope.app.interfaces.content.folder.IFolder"
- permission="zope.ManageContent"
- factory="zope.app.container.copypastemove.CopySource"
+ permission="zope.ManageContent"
+ factory="zope.app.container.copypastemove.CopySource"
/>
- <adapter
+ <adapter
provides="zope.app.interfaces.container.INoChildrenCopySource"
for="zope.app.interfaces.content.folder.IFolder"
- permission="zope.ManageContent"
- factory="zope.app.container.copypastemove.NoChildrenCopySource"
+ permission="zope.ManageContent"
+ factory="zope.app.container.copypastemove.NoChildrenCopySource"
/>
- <adapter
+ <adapter
provides="zope.app.interfaces.container.IMoveSource"
for="zope.app.interfaces.content.folder.IFolder"
- permission="zope.ManageContent"
- factory="zope.app.container.copypastemove.MoveSource"
+ permission="zope.ManageContent"
+ factory="zope.app.container.copypastemove.MoveSource"
/>
- <adapter
+ <adapter
provides="zope.app.interfaces.container.IPasteTarget"
for="zope.app.interfaces.content.folder.IFolder"
- permission="zope.ManageContent"
- factory="zope.app.container.copypastemove.PasteTarget"
+ permission="zope.ManageContent"
+ factory="zope.app.container.copypastemove.PasteTarget"
/>
-
- <adapter
+
+ <adapter
provides="zope.app.interfaces.container.IPasteNamesChooser"
for="zope.app.interfaces.content.folder.IFolder"
- permission="zope.ManageContent"
- factory="zope.app.container.copypastemove.PasteNamesChooser"
+ permission="zope.ManageContent"
+ factory="zope.app.container.copypastemove.PasteNamesChooser"
/>
- <event:subscribe
- subscriber = ".dependency.CheckDependency"
- event_types = "zope.app.interfaces.event.IObjectRemovedEvent"
+ <event:subscribe
+ subscriber=".dependency.CheckDependency"
+ event_types="zope.app.interfaces.event.IObjectRemovedEvent"
/>
</zopeConfigure>
=== Zope3/src/zope/app/container/zopecontainer.py 1.18 => 1.19 ===
--- Zope3/src/zope/app/container/zopecontainer.py:1.18 Sun Jun 1 11:59:29 2003
+++ Zope3/src/zope/app/container/zopecontainer.py Wed Jun 4 10:57:56 2003
@@ -21,22 +21,23 @@
from zope.app.interfaces.container import IOptionalNamesContainer
from zope.app.interfaces.container import IContainerNamesContainer
from zope.component import queryAdapter, getAdapter
-from zope.app.context import ContextWrapper
+from zope.app.context import ContextWrapper, Wrapper
from zope.app.event import publish
from zope.app.interfaces.container import IAddNotifiable
from zope.app.interfaces.container import IDeleteNotifiable
from zope.app.interfaces.copypastemove import IObjectMover
from types import StringTypes
-from zope.proxy import removeAllProxies
+from zope.proxy import removeAllProxies, getProxiedObject
from zope.exceptions import NotFoundError, DuplicationError
-from zope.app.event.objectevent \
- import ObjectRemovedEvent, ObjectModifiedEvent, ObjectAddedEvent
+from zope.app.event.objectevent import ObjectRemovedEvent
+from zope.app.event.objectevent import ObjectModifiedEvent, ObjectAddedEvent
+from zope.interface import implements
_marker = object()
class ZopeContainerAdapter:
- __implements__ = IZopeContainer
+ implements(IZopeContainer)
def __init__(self, container):
self.context = container
@@ -178,6 +179,135 @@
target = self.context
if target.__contains__(newKey):
+ raise DuplicationError("name, %s, is already in use" % newKey)
+
+ if mover.moveable() and mover.moveableTo(target, newKey):
+ # the mover will call beforeDeleteHook hook for us
+ mover.moveTo(target, newKey)
+ # the mover will call the afterAddHook hook for us
+ # the mover will publish an ObjectMovedEvent for us
+
+class ZopeContainerDecorator(Wrapper):
+ implements(IZopeContainer)
+
+ def __getitem__(self, key):
+ "See IZopeItemContainer"
+ container = getProxiedObject(self)
+ value = container[key]
+ return ContextWrapper(value, self, name=key)
+
+ def get(self, key, default=None):
+ "See IZopeSimpleReadContainer"
+ container = getProxiedObject(self)
+ value = container.get(key, _marker)
+ if value is not _marker:
+ return ContextWrapper(value, self, name=key)
+ else:
+ return default
+
+ def values(self):
+ "See IZopeReadContainer"
+ container = getProxiedObject(self)
+ result = []
+ for key, value in container.items():
+ result.append(ContextWrapper(value, self, name=key))
+ return result
+
+ def items(self):
+ "See IZopeReadContainer"
+ container = getProxiedObject(self)
+ result = []
+ for key, value in container.items():
+ result.append((key, ContextWrapper(value, self, name=key)))
+ return result
+
+ def setObject(self, key, object):
+ "See IZopeWriteContainer"
+ if not isinstance(key, StringTypes):
+ raise TypeError("Item name is not a string.")
+
+ container = getProxiedObject(self)
+
+ if not key:
+ if not (IOptionalNamesContainer.isImplementedBy(container)
+ or IContainerNamesContainer.isImplementedBy(container)):
+ raise ValueError("Empty names are not allowed")
+
+ # We remove the proxies from the object before adding it to
+ # the container, because we can't store proxies.
+ object = removeAllProxies(object)
+
+ # Add the object
+ key = container.setObject(key, object)
+
+ # Publish an added event
+ # We explicitly get the object back from the container with
+ # container[key], because some kinds of container may choose
+ # to store a different object than the exact one we added.
+ object = self[key]
+ publish(self, ObjectAddedEvent(object))
+
+ # Call the after add hook, if necessary
+ adapter = queryAdapter(object, IAddNotifiable)
+ if adapter is not None:
+ adapter.afterAddHook(object, self)
+
+ publish(self, ObjectModifiedEvent(self))
+ return key
+
+ def __delitem__(self, key):
+ "See IZopeWriteContainer"
+ container = getProxiedObject(self)
+
+ object = ContextWrapper(container[key], self, name=key)
+
+ # Call the before delete hook, if necessary
+ adapter = queryAdapter(object, IDeleteNotifiable)
+ if adapter is not None:
+ adapter.beforeDeleteHook(object, self)
+ elif hasattr(object, 'beforeDeleteHook'):
+ # XXX: Ideally, only do this in debug mode.
+ from warnings import warn
+ warn('Class %s has beforeDeleteHook but is not'
+ ' IDeleteNotifiable' % object.__class__)
+
+ del container[key]
+
+ publish(self, ObjectRemovedEvent(object))
+ publish(self, ObjectModifiedEvent(self))
+
+ return key
+
+ def rename(self, currentKey, newKey):
+ """Put the object found at 'currentKey' under 'newKey' instead.
+
+ The container can choose different or modified 'newKey'. The
+ 'newKey' that was used is returned.
+
+ If the object at 'currentKey' is IMoveNotifiable, its
+ beforeDeleteHook method is called, with a movingTo
+ argument of the container's path plus the 'newKey'.
+ Otherwise, if the object at 'currentKey' is IDeleteNotifiable,
+ its beforeDeleteHook method is called.
+
+ Then, the object is removed from the container using the
+ container's __del__ method.
+
+ Then, If the object is IMoveNotifiable, its afterAddHook
+ method is called, with a movedFrom argument of the container's
+ path plus the 'currentKey'.
+ Otherwise, if the object is IAddNotifiable, its afterAddHook
+ method is called.
+
+ Then, an IObjectMovedEvent is published.
+ """
+ object = self.get(currentKey)
+ if object is None:
+ raise NotFoundError(self, currentKey)
+ mover = getAdapter(object, IObjectMover)
+ target = self
+
+ if newKey in target:
raise DuplicationError("name, %s, is already in use" % newKey)
if mover.moveable() and mover.moveableTo(target, newKey):