[Zope3-checkins] CVS: Zope3/src/zope/app - decorator.py:1.1.2.1 location.py:1.1.2.1 attributeannotations.py:1.6.24.1 configure.zcml:1.35.2.1 copypastemove.py:1.10.24.1 zapi.py:1.10.2.1 context.py:NONE

Jim Fulton jim at zope.com
Mon Sep 8 15:22:20 EDT 2003


Update of /cvs-repository/Zope3/src/zope/app
In directory cvs.zope.org:/tmp/cvs-serv20092/src/zope/app

Modified Files:
      Tag: parentgeddon-branch
	attributeannotations.py configure.zcml copypastemove.py 
	zapi.py 
Added Files:
      Tag: parentgeddon-branch
	decorator.py location.py 
Removed Files:
      Tag: parentgeddon-branch
	context.py 
Log Message:
Checking in work in progress on parentgeddon-branch so Fred can help
me to get the tests passing.  Specific log entries will be provided
when we merge this into the head.


=== Added File Zope3/src/zope/app/decorator.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Decorator support

Decorators are proxies that are mostly transparent but that may provide
additional features.

$Id: decorator.py,v 1.1.2.1 2003/09/08 18:21:18 jim Exp $
"""
from zope.proxy import getProxiedObject, ProxyBase
from zope.security.checker import selectChecker, CombinedChecker
from zope.interface.declarations import ObjectSpecificationDescriptor
from zope.interface.declarations import getObjectSpecification

class DecoratorSpecificationDescriptor(ObjectSpecificationDescriptor):
    """Support for interface declarations on decorators

    >>> from zope.interface import *
    >>> class I1(Interface):
    ...     pass
    >>> class I2(Interface):
    ...     pass
    >>> class I3(Interface):
    ...     pass
    >>> class I4(Interface):
    ...     pass

    >>> class D1(Decorator):
    ...   implements(I1)


    >>> class D2(Decorator):
    ...   implements(I2)

    >>> class X:
    ...   implements(I3)

    >>> x = X()
    >>> directlyProvides(x, I4)

    Interfaces of X are ordered with the directly-provided interfaces first

    >>> [interface.getName() for interface in list(providedBy(x))]
    ['I4', 'I3']

    When we decorate objects, what order should the interfaces come
    in?  One could argue that decorators are less specific, so they
    should come last.

    >>> [interface.getName() for interface in list(providedBy(D1(x)))]
    ['I4', 'I3', 'I1']

    >>> [interface.getName() for interface in list(providedBy(D2(D1(x))))]
    ['I4', 'I3', 'I1', 'I2']
    """
    def __get__(self, inst, cls=None):
        if inst is None:
            return getObjectSpecification(cls)
        else:
            provided = providedBy(getProxiedObject(inst))

            # Use type rather than __class__ because inst is a proxy and
            # will return the proxied object's class.
            cls = type(inst) 
            return ObjectSpecification(provided, cls)


class DecoratedSecurityCheckerDescriptor:
    """Descriptor for a Decorator that provides a decorated security checker.
    """
    def __get__(self, inst, cls=None):
        if inst is None:
            return self
        else:
            proxied_object = getProxiedObject(inst)
            checker = getattr(proxied_object, '__Security_checker__', None)
            if checker is None:
                checker = selectChecker(proxied_object)
            wrapper_checker = selectChecker(inst)
            if wrapper_checker is None:
                return checker
            elif checker is None:
                return wrapper_checker
            else:
                return CombinedChecker(wrapper_checker, checker)


class Decorator(ProxyBase):
    """Decorator base class
    """
    
    __providedBy__ = DecoratorSpecificationDescriptor()
    __Security_checker__ = DecoratedSecurityCheckerDescriptor()



=== Added File Zope3/src/zope/app/location.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Classes to support implenting IContained

$Id: location.py,v 1.1.2.1 2003/09/08 18:21:18 jim Exp $
"""

import zope.interface
from zope.app import zapi
from zope.app.interfaces.location import ILocation
from zope.app.interfaces.traversing import IPhysicallyLocatable
from zope.app.interfaces.traversing import IContainmentRoot
from zope.app.interfaces.traversing import ITraverser

import cPickle
import tempfile

class Location(object):
    """Stupid mix-in that defines __parent__ and __name__ attributes
    """

    zope.interface.implements(ILocation)

    __parent__ = __name__ = None


class LocationPhysicallyLocatable:
    """Provide location information for location objects
    """

    zope.interface.implements(IPhysicallyLocatable)

    def __init__(self, context):
        self.context = context

    def getRoot(self):
        """Get the root location for a location.

        See IPhysicallyLocatable

        The root location is a location that contains the given
        location and that implements IContainmentRoot.

        >>> root = Location()
        >>> zope.interface.directlyProvides(root, IContainmentRoot)
        >>> LocationPhysicallyLocatable(root).getRoot() is root
        1

        >>> o1 = Location(); o1.__parent__ = root
        >>> LocationPhysicallyLocatable(o1).getRoot() is root
        1
        
        >>> o2 = Location(); o2.__parent__ = o1
        >>> LocationPhysicallyLocatable(o2).getRoot() is root
        1

        We'll get a TypeError if we try to get the location fo a
        rootless object:

        >>> o1.__parent__ = None
        >>> LocationPhysicallyLocatable(o1).getRoot()
        Traceback (most recent call last):
        ...
        TypeError: Not enough context to determine location root
        >>> LocationPhysicallyLocatable(o2).getRoot() 
        Traceback (most recent call last):
        ...
        TypeError: Not enough context to determine location root

        If we screw up and create a location cycle, it will be caught:

        >>> o1.__parent__ = o2
        >>> LocationPhysicallyLocatable(o1).getRoot()
        Traceback (most recent call last):
        ...
        TypeError: Maximim location depth exceeded, """ \
                """probably due to a a location cycle.

        """
        context = self.context
        max = 9999
        while context is not None:
            if IContainmentRoot.isImplementedBy(context):
                return context
            context = context.__parent__
            max -= 1
            if max < 1:
                raise TypeError("Maximim location depth exceeded, "
                                "probably due to a a location cycle.")

        raise TypeError("Not enough context to determine location root")
        
    def getPath(self):
        """Get the path of a location.
        
        See IPhysicallyLocatable

        This is an "absolute path", rooted at a root object.

        >>> root = Location()
        >>> zope.interface.directlyProvides(root, IContainmentRoot)
        >>> LocationPhysicallyLocatable(root).getPath()
        u'/'

        >>> o1 = Location(); o1.__parent__ = root; o1.__name__ = 'o1'
        >>> LocationPhysicallyLocatable(o1).getPath()
        u'/o1'

        >>> o2 = Location(); o2.__parent__ = o1; o2.__name__ = u'o2'
        >>> LocationPhysicallyLocatable(o2).getPath()
        u'/o1/o2'

        It is an error to get the path of a rootless location:

        >>> o1.__parent__ = None
        >>> LocationPhysicallyLocatable(o1).getPath()
        Traceback (most recent call last):
        ...
        TypeError: Not enough context to determine location root

        >>> LocationPhysicallyLocatable(o2).getPath() 
        Traceback (most recent call last):
        ...
        TypeError: Not enough context to determine location root

        If we screw up and create a location cycle, it will be caught:

        >>> o1.__parent__ = o2
        >>> LocationPhysicallyLocatable(o1).getPath()
        Traceback (most recent call last):
        ...
        TypeError: Maximim location depth exceeded, """ \
                """probably due to a a location cycle.
        
        """
        
        path = []
        context = self.context
        max = 9999
        while context is not None:
            if IContainmentRoot.isImplementedBy(context):
                if path:
                    path.append('')
                    path.reverse()
                    return u'/'.join(path)
                else:
                    return u'/'
            path.append(context.__name__)
            context = context.__parent__
            max -= 1
            if max < 1:
                raise TypeError("Maximim location depth exceeded, "
                                "probably due to a a location cycle.")

        raise TypeError("Not enough context to determine location root")

    def getName(self):
        """Get a location name

        See IPhysicallyLocatable.

        >>> o1 = Location(); o1.__name__ = 'o1'
        >>> LocationPhysicallyLocatable(o1).getName() 
        'o1'
        
        """
        return self.context.__name__
    



def inside(l1, l2):
    """Is l1 inside l2

    L1 is inside l2 if l2 is an ancestor of l1.

    >>> o1 = Location()
    >>> o2 = Location(); o2.__parent__ = o1
    >>> o3 = Location(); o3.__parent__ = o2
    >>> o4 = Location(); o4.__parent__ = o3

    >>> inside(o1, o1)
    1
    >>> inside(o2, o1)
    1
    >>> inside(o3, o1)
    1
    >>> inside(o4, o1)
    1
    
    >>> inside(o1, o4)
    0

    >>> inside(o1, None)
    0
    
    """

    while l1 is not None:
        if l1 is l2:
            return True
        l1 = l1.__parent__

    return False
    
    
def locationCopy(loc):
    """Return a copy of an object,, and anything in it

    If object in the location refer to objects outside of the
    location, then the copies of the objects in the location refer to
    the same outside objects.

    For example, suppose we have an object (location) hierarchy like this:

           o1
          /  \
        o2    o3
        |     |
        o4    o5

    >>> o1 = Location()
    >>> o1.o2 = Location(); o1.o2.__parent__ = o1
    >>> o1.o3 = Location(); o1.o3.__parent__ = o1
    >>> o1.o2.o4 = Location(); o1.o2.o4.__parent__ = o1.o2
    >>> o1.o3.o5 = Location(); o1.o3.o5.__parent__ = o1.o3

    In addition, o3 has a non-locatin reference to o4.

    >>> o1.o3.o4 = o1.o2.o4

    When we copy o3, we should get a copy of o3 and o5, with
    references to o1 and o4.

    >>> c3 = locationCopy(o1.o3)
    >>> c3 is o1.o3
    0
    >>> c3.__parent__ is o1
    1
    >>> c3.o5 is o1.o3.o5
    0
    >>> c3.o5.__parent__ is c3
    1
    >>> c3.o4 is o1.o2.o4
    1
    
    
    """
    tmp = tempfile.TemporaryFile()
    persistent = CopyPersistent(loc)

    # Pickle the object to a temporary file
    pickler = cPickle.Pickler(tmp, 2)
    pickler.persistent_id = persistent.id
    pickler.dump(loc)

    # Now load it back
    tmp.seek(0)
    unpickler = cPickle.Unpickler(tmp)
    unpickler.persistent_load = persistent.load

    return unpickler.load()

class CopyPersistent:
    """Persistence hooks for copying locations

    See locationCopy above.

    We get initialized with an initial location:

    >>> o1 = Location()
    >>> persistent = CopyPersistent(o1)

    We provide an id function that returns None when given a non-location:

    >>> persistent.id(42)

    Or when given a location that is inside the initial location:

    >>> persistent.id(o1)
    >>> o2 = Location(); o2.__parent__ = o1
    >>> persistent.id(o2)

    But, if we get a location outside the original location, we assign
    it an id and return the id:
    
    >>> o3 = Location()
    >>> id3 = persistent.id(o3)
    >>> id3 is None
    0
    >>> o4 = Location()
    >>> id4 = persistent.id(o4)
    >>> id4 is None
    0
    >>> id4 is id3
    0

    We also provide a load function that returns the objects for which
    we were given ids:

    >>> persistent.load(id3) is o3
    1
    >>> persistent.load(id4) is o4
    1

    """
    
    def __init__(self, location):
        self.location = location
        self.others = {}
        self.load = self.others.get

    def id(self, object):
        if ILocation.isImplementedBy(object):
            if not inside(object, self.location):
                others = self.others
                pid = len(others)
                others[pid] = object
                return pid

        return None


class PathPersistent:
    """Persistence hooks for pickling locations

    See locationCopy above.

    Unlike copy persistent, we use paths for ids of outside locations
    so that we can separate pickling and unpickling in time.  We have
    to compute paths and traverse objects to load paths, but paths can
    be stored for later use, unlike the ids used by CopyPersistent.

    We require outside locations that can be adapted to ITraversable.
    To simplify the example, we'll make an traversable location:

    >>> class TLocation(Location):
    ...     zope.interface.implements(ITraverser)
    ...     def traverse(self, path, default=None, request=None):
    ...         o = self
    ...         for name in path.split(u'/'):
    ...            o = getattr(o, name)
    ...         return o

    Normally, general adapters are used to make objects traversable.

    We get initialized with an initial location:

    >>> o1 = Location()
    >>> persistent = PathPersistent(o1)
    
    We provide an id function that returns None when given a non-location:

    >>> persistent.id(42)

    Or when given a location that is inside the initial location:

    >>> persistent.id(o1)
    >>> o2 = Location(); o2.__parent__ = o1
    >>> persistent.id(o2)

    But, if we get a location outside the original location, we return it's
    path. To compute it's path, it must be rooted:

    >>> root = TLocation()
    >>> zope.interface.directlyProvides(root, IContainmentRoot)
    >>> o3 = TLocation(); o3.__name__ = 'o3'
    >>> o3.__parent__ = root; root.o3 = o3
    >>> persistent.id(o3)
    u'/o3'

    >>> o4 = TLocation(); o4.__name__ = 'o4'
    >>> o4.__parent__ = o3; o3.o4 = o4
    >>> persistent.id(o4)
    u'/o3/o4'
    

    We also provide a load function that returns objects by traversing
    given paths.  It has to find the root based on the object given to
    the constructor.  Therefore, that object must also be rooted:

    >>> o1.__parent__ = root
    >>> persistent.load(u'/o3') is o3
    1
    >>> persistent.load(u'/o3/o4') is o4
    1

    """
    
    def __init__(self, location):
        self.location = location

    def id(self, object):
        if ILocation.isImplementedBy(object):
            if not inside(object, self.location):
                return LocationPhysicallyLocatable(object).getPath()

        return None

    def load(self, path):
        if path[:1] != u'/':
            raise ValueError("ZPersistent paths must be absolute", path)
        root = LocationPhysicallyLocatable(self.location).getRoot()
        return zapi.getAdapter(root, ITraverser).traverse(path[1:])


=== Zope3/src/zope/app/attributeannotations.py 1.6 => 1.6.24.1 ===
--- Zope3/src/zope/app/attributeannotations.py:1.6	Tue Jun  3 11:33:55 2003
+++ Zope3/src/zope/app/attributeannotations.py	Mon Sep  8 14:21:18 2003
@@ -19,8 +19,8 @@
 from zodb.btrees.OOBTree import OOBTree
 from zope.app.interfaces.annotation import IAnnotations
 from zope.proxy import removeAllProxies
-from zope.app.context import ContextWrapper
 from zope.interface import implements
+from zope.app.interfaces.location import ILocation
 
 class AttributeAnnotations:
     """
@@ -39,17 +39,28 @@
         self.unwrapped_obj = removeAllProxies(obj)
 
     def __getitem__(self, key):
-        annotations = getattr(self.unwrapped_obj, '__annotations__', {})
-        return ContextWrapper(annotations[key], self.wrapped_obj)
+        annotations = getattr(self.unwrapped_obj, '__annotations__', None)
+        if annotations is None:
+            raise KeyError, key
+        return annotations[key]
+
+    def __setitem__(self, key, value):
+        if ILocation.isImplementedBy(value):
+            value.__parent__ = self.unwrapped_obj
+
+        try:
+            annotations = self.unwrapped_obj.__annotations__
+        except AttributeError:
+            annotations = self.unwrapped_obj.__annotations__ = OOBTree()
+
+        annotations[key] = value
 
     def get(self, key, default=None):
         try:
-            value = self.unwrapped_obj.__annotations__.get(key, default)
+            return self.unwrapped_obj.__annotations__.get(key, default)
         except AttributeError:
             # I guess default shouldn't be wrapped.
             return default
-        else:
-            return ContextWrapper(value, self.wrapped_obj)
 
     def __getattr__(self, name):
         # this method is for getting methods and attributes of the
@@ -62,4 +73,5 @@
                 attr = getattr(annotations, name)
             else:
                 raise
-        return ContextWrapper(attr, self.wrapped_obj)
+            
+        return attr


=== Zope3/src/zope/app/configure.zcml 1.35 => 1.35.2.1 ===
--- Zope3/src/zope/app/configure.zcml:1.35	Tue Sep  2 16:45:32 2003
+++ Zope3/src/zope/app/configure.zcml	Mon Sep  8 14:21:18 2003
@@ -87,6 +87,12 @@
       provides="zope.app.interfaces.copypastemove.IPrincipalClipboard"
       for="zope.app.interfaces.annotation.IAnnotations" />
 
+  <adapter 
+      for=".interfaces.location.ILocation"
+      provides=".interfaces.traversing.IPhysicallyLocatable"
+      factory=".location.LocationPhysicallyLocatable" 
+      />
+
   <include package="zope.app.container" />
   <include package="zope.app.content" />
   <include package="zope.app.services" />


=== Zope3/src/zope/app/copypastemove.py 1.10 => 1.10.24.1 ===
--- Zope3/src/zope/app/copypastemove.py:1.10	Fri Jun 13 13:41:10 2003
+++ Zope3/src/zope/app/copypastemove.py	Mon Sep  8 14:21:18 2003
@@ -17,8 +17,7 @@
 $Id$
 """
 
-from zope.app.traversing import getParent, getName, getPath
-from zope.component import getAdapter, queryAdapter
+from zope.app import zapi
 from zope.app.interfaces.copypastemove import IObjectMover
 from zope.app.interfaces.copypastemove import IObjectCopier
 from zope.app.interfaces.copypastemove import INoChildrenObjectCopier
@@ -34,6 +33,7 @@
 from zope.app.event import publish
 from zope.proxy import removeAllProxies
 from zope.interface import implements
+from zope.exceptions import NotFoundError, DuplicationError
 
 class ObjectMover:
     '''Use getAdapter(obj, IObjectMover) to move an object somewhere.'''
@@ -50,32 +50,33 @@
         Typically, the target is adapted to IPasteTarget.'''
 
         obj = self.context
-        container = getParent(obj)
-        orig_name = getName(obj)
+        container = zapi.getParent(obj)
+        orig_name = zapi.getName(obj)
         if new_name is None:
             new_name = orig_name
 
-        movesource = getAdapter(container, IMoveSource)
-        target_path = getPath(target)
-        source_path = getPath(container)
+        movesource = zapi.getAdapter(container, IMoveSource)
+        target_path = zapi.getPath(target)
+        source_path = zapi.getPath(container)
 
-        if queryAdapter(obj, IMoveNotifiable):
-            getAdapter(obj, IMoveNotifiable).beforeDeleteHook(
+        if zapi.queryAdapter(obj, IMoveNotifiable):
+            zapi.getAdapter(obj, IMoveNotifiable).beforeDeleteHook(
                 obj, container, movingTo=target_path)
-        elif queryAdapter(obj, IDeleteNotifiable):
-            getAdapter(obj, IDeleteNotifiable).beforeDeleteHook(obj, container)
+        elif zapi.queryAdapter(obj, IDeleteNotifiable):
+            zapi.getAdapter(obj, IDeleteNotifiable
+                            ).beforeDeleteHook(obj, container)
 
         new_obj = movesource.removeObject(orig_name, target)
-        pastetarget = getAdapter(target, IPasteTarget)
+        pastetarget = zapi.getAdapter(target, IPasteTarget)
         # publish an ObjectCreatedEvent (perhaps...?)
         new_name = pastetarget.pasteObject(new_name, new_obj)
 
         # call afterAddHook
-        if queryAdapter(new_obj, IMoveNotifiable):
-            getAdapter(new_obj, IMoveNotifiable).afterAddHook(
+        if zapi.queryAdapter(new_obj, IMoveNotifiable):
+            zapi.getAdapter(new_obj, IMoveNotifiable).afterAddHook(
                 new_obj, container, movedFrom=source_path)
-        elif queryAdapter(new_obj, IAddNotifiable):
-            getAdapter(new_obj, IAddNotifiable).afterAddHook(
+        elif zapi.queryAdapter(new_obj, IAddNotifiable):
+            zapi.getAdapter(new_obj, IAddNotifiable).afterAddHook(
                 new_obj, container)
 
         # publish ObjectMovedEvent
@@ -96,8 +97,8 @@
         '''
         obj = self.context
         if name is None:
-            name = getName(obj)
-        pastetarget = getAdapter(target, IPasteTarget)
+            name = zapi.getName(obj)
+        pastetarget = zapi.getAdapter(target, IPasteTarget)
         return pastetarget.acceptsObject(name, obj)
 
 class ObjectCopier:
@@ -119,27 +120,27 @@
         an IObjectCreated event should be published.
         """
         obj = self.context
-        container = getParent(obj)
-        orig_name = getName(obj)
+        container = zapi.getParent(obj)
+        orig_name = zapi.getName(obj)
         if new_name is None:
             new_name = orig_name
 
-        target_path = getPath(target)
-        source_path = getPath(container)
+        target_path = zapi.getPath(target)
+        source_path = zapi.getPath(container)
 
-        copysource = getAdapter(container, ICopySource)
+        copysource = zapi.getAdapter(container, ICopySource)
         obj = copysource.copyObject(orig_name, target_path)
 
-        pastetarget = getAdapter(target, IPasteTarget)
+        pastetarget = zapi.getAdapter(target, IPasteTarget)
         # publish an ObjectCreatedEvent (perhaps...?)
         new_name = pastetarget.pasteObject(new_name, obj)
 
         # call afterAddHook
-        if queryAdapter(obj, ICopyNotifiable):
-            getAdapter(obj, ICopyNotifiable).afterAddHook(
+        if zapi.queryAdapter(obj, ICopyNotifiable):
+            zapi.getAdapter(obj, ICopyNotifiable).afterAddHook(
                 obj, container, copiedFrom=source_path)
-        elif queryAdapter(obj, IAddNotifiable):
-            getAdapter(obj, IAddNotifiable).afterAddHook(obj, container)
+        elif zapi.queryAdapter(obj, IAddNotifiable):
+            zapi.getAdapter(obj, IAddNotifiable).afterAddHook(obj, container)
 
         # publish ObjectCopiedEvent
         publish(container,
@@ -159,8 +160,8 @@
         '''
         obj = self.context
         if name is None:
-            name = getName(obj)
-        pastetarget = getAdapter(target, IPasteTarget)
+            name = zapi.getName(obj)
+        pastetarget = zapi.getAdapter(target, IPasteTarget)
         return pastetarget.acceptsObject(name, obj)
 
 
@@ -183,31 +184,31 @@
         an IObjectCreated event should be published.
         """
         obj = self.context
-        container = getParent(obj)
-        orig_name = getName(obj)
+        container = zapi.getParent(obj)
+        orig_name = zapi.getName(obj)
         if new_name is None:
             new_name = orig_name
 
-        target_path = getPath(target)
-        source_path = getPath(container)
+        target_path = zapi.getPath(target)
+        source_path = zapi.getPath(container)
 
-        copysource = getAdapter(container, INoChildrenCopySource)
+        copysource = zapi.getAdapter(container, INoChildrenCopySource)
         obj = copysource.copyObjectWithoutChildren(orig_name, target_path)
         if obj is None:
             raise CopyException(container, orig_name,
                                 'Could not get a copy without children of %s'
                                 % orig_name) 
 
-        pastetarget = getAdapter(target, IPasteTarget)
+        pastetarget = zapi.getAdapter(target, IPasteTarget)
         # publish an ObjectCreatedEvent (perhaps...?)
         new_name = pastetarget.pasteObject(new_name, obj)
 
         # call afterAddHook
-        if queryAdapter(obj, ICopyNotifiable):
-            getAdapter(obj, ICopyNotifiable).afterAddHook(
+        if zapi.queryAdapter(obj, ICopyNotifiable):
+            zapi.getAdapter(obj, ICopyNotifiable).afterAddHook(
                 obj, container, copiedFrom=source_path)
-        elif queryAdapter(obj, IAddNotifiable):
-            getAdapter(obj, IAddNotifiable).afterAddHook(obj, container)
+        elif zapi.queryAdapter(obj, IAddNotifiable):
+            zapi.getAdapter(obj, IAddNotifiable).afterAddHook(obj, container)
 
         # publish ObjectCopiedEvent
         publish(container, ObjectCopiedEvent(
@@ -245,3 +246,18 @@
         '''Return the contents of the clipboard'''
         return removeAllProxies(self.context.get('clipboard', ()))
 
+
+def rename(container, oldid, newid):
+    object = container.get(oldid)
+    if object is None:
+        raise NotFoundError(self, oldid)
+    mover = zapi.getAdapter(object, IObjectMover)
+
+    if newid in container:
+        raise DuplicationError("name, %s, is already in use" % newid)
+
+    if mover.moveable() and mover.moveableTo(container, newid):
+        # the mover will call beforeDeleteHook hook for us
+        mover.moveTo(container, newid)
+        # the mover will call the afterAddHook hook for us
+        # the mover will publish an ObjectMovedEvent for us


=== Zope3/src/zope/app/zapi.py 1.10 => 1.10.2.1 ===
--- Zope3/src/zope/app/zapi.py:1.10	Wed Sep  3 14:33:54 2003
+++ Zope3/src/zope/app/zapi.py	Mon Sep  8 14:21:18 2003
@@ -20,17 +20,18 @@
 
 from zope.app.interfaces.zapi import IZAPI
 from zope.interface import moduleProvides
-from zope.context import getWrapperData
 
 moduleProvides(IZAPI)
 __all__ = tuple(IZAPI)
 
 from zope.component import *
+
 # XXX: 'queryService' is not part of IComponentArchitecture;
 # XXX: Jim says you shouldn't need it anyway.
+# YYY: So why is it here?
+
 from zope.component import queryService
-from zope.context import *
-from zope.app.context import *
+
 from zope.app.traversing import *
 from zope.app.interfaces.exceptions import UserError
 

=== Removed File Zope3/src/zope/app/context.py ===




More information about the Zope3-Checkins mailing list