[Checkins] SVN: zope.copypastemove/tags/3.5.1/ Tag 3.5.1

Dan Korostelev nadako at gmail.com
Sun Feb 8 18:03:23 EST 2009


Log message for revision 96289:
  Tag 3.5.1

Changed:
  A   zope.copypastemove/tags/3.5.1/
  D   zope.copypastemove/tags/3.5.1/CHANGES.txt
  A   zope.copypastemove/tags/3.5.1/CHANGES.txt
  D   zope.copypastemove/tags/3.5.1/setup.py
  A   zope.copypastemove/tags/3.5.1/setup.py
  D   zope.copypastemove/tags/3.5.1/src/zope/copypastemove/DEPENDENCIES.cfg
  D   zope.copypastemove/tags/3.5.1/src/zope/copypastemove/__init__.py
  A   zope.copypastemove/tags/3.5.1/src/zope/copypastemove/__init__.py
  D   zope.copypastemove/tags/3.5.1/src/zope/copypastemove/interfaces.py
  A   zope.copypastemove/tags/3.5.1/src/zope/copypastemove/interfaces.py

-=-
Deleted: zope.copypastemove/tags/3.5.1/CHANGES.txt
===================================================================
--- zope.copypastemove/trunk/CHANGES.txt	2009-02-08 17:03:40 UTC (rev 96257)
+++ zope.copypastemove/tags/3.5.1/CHANGES.txt	2009-02-08 23:03:23 UTC (rev 96289)
@@ -1,28 +0,0 @@
-Changes
-=======
-
-3.5.1 (unreleased)
-------------------
-
-* ...
-
-3.5.0 (2009-01-31)
-------------------
-
-* Use zope.container instead of zope.app.container.
-
-3.4.1 (2009-01-26)
-------------------
-
-* Moved the test dependencies to a `test` extra requirement.
-
-3.4.0 (2007-09-28)
-------------------
-
-* No further changes since 3.4.0a1.
-
-3.4.0a1 (2007-04-22)
---------------------
-
-* Initial release as a separate project, corresponds to
-  zope.copypastemove from Zope 3.4.0a1

Copied: zope.copypastemove/tags/3.5.1/CHANGES.txt (from rev 96287, zope.copypastemove/trunk/CHANGES.txt)
===================================================================
--- zope.copypastemove/tags/3.5.1/CHANGES.txt	                        (rev 0)
+++ zope.copypastemove/tags/3.5.1/CHANGES.txt	2009-02-08 23:03:23 UTC (rev 96289)
@@ -0,0 +1,35 @@
+=======
+CHANGES
+=======
+
+3.5.1 (2009-02-09)
+------------------
+
+- Use the new zope.copy package for ObjectCopier to provide pluggable
+  copying mechanism that is not dependent on zope.location hardly.
+
+- Move the ItemNotFoundError exception to the interfaces module as
+  it's part of public API. Old import still works as we actually
+  use it where it was previously defined, however, the new import
+  place is preferred.
+
+3.5.0 (2009-01-31)
+------------------
+
+- Use zope.container instead of zope.app.container.
+
+3.4.1 (2009-01-26)
+------------------
+
+- Moved the test dependencies to a `test` extra requirement.
+
+3.4.0 (2007-09-28)
+------------------
+
+- No further changes since 3.4.0a1.
+
+3.4.0a1 (2007-04-22)
+--------------------
+
+- Initial release as a separate project, corresponds to
+  zope.copypastemove from Zope 3.4.0a1

Deleted: zope.copypastemove/tags/3.5.1/setup.py
===================================================================
--- zope.copypastemove/trunk/setup.py	2009-02-08 17:03:40 UTC (rev 96257)
+++ zope.copypastemove/tags/3.5.1/setup.py	2009-02-08 23:03:23 UTC (rev 96289)
@@ -1,57 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (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.
-#
-##############################################################################
-"""Setup for zope.copypastemove package
-
-$Id$
-"""
-import os
-from setuptools import setup, find_packages
-
-long_description = (open('README.txt').read() +
-                    '\n\n' +
-                    open('CHANGES.txt').read())
-
-setup(name='zope.copypastemove',
-      version = '3.5.1dev',
-      url='http://pypi.python.org/pypi/zope.copypastemove',
-      license='ZPL 2.1',
-      author='Zope Corporation and Contributors',
-      author_email='zope-dev at zope.org',
-      description="Copy, Paste and Move support for content components.",
-      long_description=long_description,
-      classifiers=['Environment :: Web Environment',
-                   'Intended Audience :: Developers',
-                   'License :: OSI Approved :: Zope Public License',
-                   'Programming Language :: Python',
-                   'Framework :: Zope3',
-                   ],
-
-      packages=find_packages('src'),
-      package_dir = {'': 'src'},
-      namespace_packages=['zope',],
-      extras_require=dict(
-          test=['zope.app.testing', 'zope.app.principalannotation']),
-      install_requires=['setuptools',
-                        'zope.container',
-                        'zope.interface',
-                        'zope.exceptions',
-                        'zope.component',
-                        'zope.event',
-                        'zope.location',
-                        'zope.annotation',
-                        'zope.lifecycleevent',
-                        ],
-      include_package_data = True,
-      zip_safe = False,
-      )

Copied: zope.copypastemove/tags/3.5.1/setup.py (from rev 96287, zope.copypastemove/trunk/setup.py)
===================================================================
--- zope.copypastemove/tags/3.5.1/setup.py	                        (rev 0)
+++ zope.copypastemove/tags/3.5.1/setup.py	2009-02-08 23:03:23 UTC (rev 96289)
@@ -0,0 +1,59 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Setup for zope.copypastemove package
+
+$Id$
+"""
+import os
+from setuptools import setup, find_packages
+
+long_description = (open('README.txt').read() +
+                    '\n\n' +
+                    open('CHANGES.txt').read())
+
+setup(name='zope.copypastemove',
+      version = '3.5.1',
+      url='http://pypi.python.org/pypi/zope.copypastemove',
+      license='ZPL 2.1',
+      author='Zope Corporation and Contributors',
+      author_email='zope-dev at zope.org',
+      description="Copy, Paste and Move support for content components.",
+      long_description=long_description,
+      classifiers=['Environment :: Web Environment',
+                   'Intended Audience :: Developers',
+                   'License :: OSI Approved :: Zope Public License',
+                   'Programming Language :: Python',
+                   'Framework :: Zope3',
+                   ],
+
+      packages=find_packages('src'),
+      package_dir = {'': 'src'},
+      namespace_packages=['zope',],
+      extras_require=dict(
+          test=['zope.app.testing',
+                'zope.app.principalannotation']),
+      install_requires=['setuptools',
+                        'zope.annotation',
+                        'zope.component',
+                        'zope.container',
+                        'zope.copy',
+                        'zope.event',
+                        'zope.exceptions',
+                        'zope.interface',
+                        'zope.lifecycleevent',
+                        'zope.location',
+                        ],
+      include_package_data = True,
+      zip_safe = False,
+      )

Deleted: zope.copypastemove/tags/3.5.1/src/zope/copypastemove/DEPENDENCIES.cfg
===================================================================
--- zope.copypastemove/trunk/src/zope/copypastemove/DEPENDENCIES.cfg	2009-02-08 17:03:40 UTC (rev 96257)
+++ zope.copypastemove/tags/3.5.1/src/zope/copypastemove/DEPENDENCIES.cfg	2009-02-08 23:03:23 UTC (rev 96289)
@@ -1,13 +0,0 @@
-zope.interface
-zope.exceptions
-zope.component
-zope.event
-zope.location
-zope.annotation
-zope.lifecycleevent
-zope.app.container
-
-#for testing
-zope.testing
-zope.app.component
-zope.app.principalannotation

Deleted: zope.copypastemove/tags/3.5.1/src/zope/copypastemove/__init__.py
===================================================================
--- zope.copypastemove/trunk/src/zope/copypastemove/__init__.py	2009-02-08 17:03:40 UTC (rev 96257)
+++ zope.copypastemove/tags/3.5.1/src/zope/copypastemove/__init__.py	2009-02-08 23:03:23 UTC (rev 96289)
@@ -1,679 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (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.
-#
-##############################################################################
-"""Copy, Paste and Move support for content components
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-import zope.component
-from zope.interface import implements, Invalid
-from zope.exceptions import DuplicationError
-from zope.component import adapts
-from zope.event import notify
-from zope.location.pickling import locationCopy
-from zope.location.interfaces import ISublocations
-from zope.annotation.interfaces import IAnnotations
-from zope.annotation.interfaces import IAnnotations
-from zope.lifecycleevent import ObjectCopiedEvent
-
-from zope.copypastemove.interfaces import IObjectMover
-from zope.copypastemove.interfaces import IObjectCopier
-from zope.copypastemove.interfaces import IContainerItemRenamer
-from zope.copypastemove.interfaces import IPrincipalClipboard
-from zope.copypastemove.interfaces import IItemNotFoundError
-
-from zope.container.sample import SampleContainer
-from zope.container.interfaces import IContainer, IOrderedContainer
-from zope.container.interfaces import IContained
-from zope.container.interfaces import INameChooser
-from zope.container.constraints import checkObject
-
-class ItemNotFoundError(LookupError):
-    implements(IItemNotFoundError)
-
-class ObjectMover(object):
-    """Adapter for moving objects between containers
-
-    To use an object mover, pass a contained `object` to the class.
-    The contained `object` should implement `IContained`.  It should be
-    contained in a container that has an adapter to `INameChooser`.
-
-
-    >>> from zope.container.contained import Contained
-    >>> ob = Contained()
-    >>> container = ExampleContainer()
-    >>> container[u'foo'] = ob
-    >>> mover = ObjectMover(ob)
-
-    In addition to moving objects, object movers can tell you if the
-    object is movable:
-
-    >>> mover.moveable()
-    True
-
-    which, at least for now, they always are.  A better question to
-    ask is whether we can move to a particular container. Right now,
-    we can always move to a container of the same class:
-
-    >>> container2 = ExampleContainer()
-    >>> mover.moveableTo(container2)
-    True
-    >>> mover.moveableTo({})
-    Traceback (most recent call last):
-    ...
-    TypeError: Container is not a valid Zope container.
-
-    Of course, once we've decided we can move an object, we can use
-    the mover to do so:
-
-    >>> mover.moveTo(container2)
-    u'foo'
-    >>> list(container)
-    []
-    >>> list(container2)
-    [u'foo']
-    >>> ob.__parent__ is container2
-    True
-
-    We can also specify a name:
-
-    >>> mover.moveTo(container2, u'bar')
-    u'bar'
-    >>> list(container2)
-    [u'bar']
-    >>> ob.__parent__ is container2
-    True
-    >>> ob.__name__
-    u'bar'
-
-    But we may not use the same name given, if the name is already in
-    use:
-
-    >>> container2[u'splat'] = 1
-    >>> mover.moveTo(container2, u'splat')
-    u'splat_'
-    >>> l = list(container2)
-    >>> l.sort()
-    >>> l
-    [u'splat', u'splat_']
-    >>> ob.__name__
-    u'splat_'
-
-
-    If we try to move to an invalid container, we'll get an error:
-
-    >>> mover.moveTo({})
-    Traceback (most recent call last):
-    ...
-    TypeError: Container is not a valid Zope container.
-
-
-    Do a test for preconditions:
-
-    >>> import zope.interface
-    >>> import zope.schema
-    >>> def preNoZ(container, name, ob):
-    ...     "Silly precondition example"
-    ...     if name.startswith("Z"):
-    ...         raise zope.interface.Invalid("Invalid name.")
-
-    >>> class I1(zope.interface.Interface):
-    ...     def __setitem__(name, on):
-    ...         "Add an item"
-    ...     __setitem__.precondition = preNoZ
-
-    >>> from zope.container.interfaces import IContainer
-    >>> class C1(object):
-    ...     zope.interface.implements(I1, IContainer)
-    ...     def __repr__(self):
-    ...         return 'C1'
-
-    >>> from zope.container.constraints import checkObject
-    >>> container3 = C1()
-    >>> mover.moveableTo(container3, 'ZDummy')
-    False
-    >>> mover.moveableTo(container3, 'newName')
-    True
-
-    And a test for constraints:
-
-    >>> def con1(container):
-    ...     "silly container constraint"
-    ...     if not hasattr(container, 'x'):
-    ...         return False
-    ...     return True
-    ...
-    >>> class I2(zope.interface.Interface):
-    ...     __parent__ = zope.schema.Field(constraint=con1)
-    ...
-    >>> class constrainedObject(object):
-    ...     zope.interface.implements(I2)
-    ...     def __init__(self):
-    ...         self.__name__ = 'constrainedObject'
-    ...
-    >>> cO = constrainedObject()
-    >>> mover2 = ObjectMover(cO)
-    >>> mover2.moveableTo(container)
-    False
-    >>> container.x = 1
-    >>> mover2.moveableTo(container)
-    True
-
-    """
-
-    adapts(IContained)
-
-    implements(IObjectMover)
-
-    def __init__(self, object):
-        self.context = object
-        self.__parent__ = object # TODO: see if we can automate this
-
-    def moveTo(self, target, new_name=None):
-        """Move this object to the `target` given.
-
-        Returns the new name within the `target`
-        Typically, the `target` is adapted to `IPasteTarget`."""
-
-        obj = self.context
-        container = obj.__parent__
-
-        orig_name = obj.__name__
-        if new_name is None:
-            new_name = orig_name
-
-        checkObject(target, new_name, obj)
-
-        if target is container and new_name == orig_name:
-            # Nothing to do
-            return
-
-        chooser = INameChooser(target)
-        new_name = chooser.chooseName(new_name, obj)
-
-        target[new_name] = obj
-        del container[orig_name]
-        return new_name
-
-    def moveable(self):
-        """Returns ``True`` if the object is moveable, otherwise ``False``."""
-        return True
-
-    def moveableTo(self, target, name=None):
-        """Say whether the object can be moved to the given target.
-
-        Returns ``True`` if it can be moved there. Otherwise, returns
-        ``False``.
-        """
-        if name is None:
-            name = self.context.__name__
-        try:
-            checkObject(target, name, self.context)
-        except Invalid:
-            return False
-        return True
-
-class ObjectCopier(object):
-    """Adapter for copying objects between containers
-
-    To use an object copier, pass a contained `object` to the class.
-    The contained `object` should implement `IContained`.  It should be
-    contained in a container that has an adapter to `INameChooser`.
-
-    >>> from zope.container.contained import Contained
-    >>> ob = Contained()
-    >>> container = ExampleContainer()
-    >>> container[u'foo'] = ob
-    >>> copier = ObjectCopier(ob)
-
-    In addition to moving objects, object copiers can tell you if the
-    object is movable:
-
-    >>> copier.copyable()
-    True
-
-    which, at least for now, they always are.  A better question to
-    ask is whether we can copy to a particular container. Right now,
-    we can always copy to a container of the same class:
-
-    >>> container2 = ExampleContainer()
-    >>> copier.copyableTo(container2)
-    True
-    >>> copier.copyableTo({})
-    Traceback (most recent call last):
-    ...
-    TypeError: Container is not a valid Zope container.
-
-    Of course, once we've decided we can copy an object, we can use
-    the copier to do so:
-
-    >>> copier.copyTo(container2)
-    u'foo'
-    >>> list(container)
-    [u'foo']
-    >>> list(container2)
-    [u'foo']
-    >>> ob.__parent__ is container
-    True
-    >>> container2[u'foo'] is ob
-    False
-    >>> container2[u'foo'].__parent__ is container2
-    True
-    >>> container2[u'foo'].__name__
-    u'foo'
-
-    We can also specify a name:
-
-    >>> copier.copyTo(container2, u'bar')
-    u'bar'
-    >>> l = list(container2)
-    >>> l.sort()
-    >>> l
-    [u'bar', u'foo']
-
-    >>> ob.__parent__ is container
-    True
-    >>> container2[u'bar'] is ob
-    False
-    >>> container2[u'bar'].__parent__ is container2
-    True
-    >>> container2[u'bar'].__name__
-    u'bar'
-
-    But we may not use the same name given, if the name is already in
-    use:
-
-    >>> copier.copyTo(container2, u'bar')
-    u'bar_'
-    >>> l = list(container2)
-    >>> l.sort()
-    >>> l
-    [u'bar', u'bar_', u'foo']
-    >>> container2[u'bar_'].__name__
-    u'bar_'
-
-
-    If we try to copy to an invalid container, we'll get an error:
-
-    >>> copier.copyTo({})
-    Traceback (most recent call last):
-    ...
-    TypeError: Container is not a valid Zope container.
-
-    Do a test for preconditions:
-
-    >>> import zope.interface
-    >>> import zope.schema
-    >>> def preNoZ(container, name, ob):
-    ...     "Silly precondition example"
-    ...     if name.startswith("Z"):
-    ...         raise zope.interface.Invalid("Invalid name.")
-
-    >>> class I1(zope.interface.Interface):
-    ...     def __setitem__(name, on):
-    ...         "Add an item"
-    ...     __setitem__.precondition = preNoZ
-
-    >>> from zope.container.interfaces import IContainer
-    >>> class C1(object):
-    ...     zope.interface.implements(I1, IContainer)
-    ...     def __repr__(self):
-    ...         return 'C1'
-
-    >>> from zope.container.constraints import checkObject
-    >>> container3 = C1()
-    >>> copier.copyableTo(container3, 'ZDummy')
-    False
-    >>> copier.copyableTo(container3, 'newName')
-    True
-
-    And a test for constraints:
-
-    >>> def con1(container):
-    ...     "silly container constraint"
-    ...     if not hasattr(container, 'x'):
-    ...         return False
-    ...     return True
-    ...
-    >>> class I2(zope.interface.Interface):
-    ...     __parent__ = zope.schema.Field(constraint=con1)
-    ...
-    >>> class constrainedObject(object):
-    ...     zope.interface.implements(I2)
-    ...     def __init__(self):
-    ...         self.__name__ = 'constrainedObject'
-    ...
-    >>> cO = constrainedObject()
-    >>> copier2 = ObjectCopier(cO)
-    >>> copier2.copyableTo(container)
-    False
-    >>> container.x = 1
-    >>> copier2.copyableTo(container)
-    True
-
-    """
-
-    adapts(IContained)
-
-    implements(IObjectCopier)
-
-    def __init__(self, object):
-        self.context = object
-        self.__parent__ = object # TODO: see if we can automate this
-
-    def copyTo(self, target, new_name=None):
-        """Copy this object to the `target` given.
-
-        Returns the new name within the `target`.
-
-        Typically, the `target` is adapted to `IPasteTarget`.
-        After the copy is added to the `target` container, publish
-        an `IObjectCopied` event in the context of the target container.
-        If a new object is created as part of the copying process, then
-        an `IObjectCreated` event should be published.
-        """
-        obj = self.context
-        container = obj.__parent__
-
-        orig_name = obj.__name__
-        if new_name is None:
-            new_name = orig_name
-
-        checkObject(target, new_name, obj)
-
-        chooser = INameChooser(target)
-        new_name = chooser.chooseName(new_name, obj)
-
-        copy = locationCopy(obj)
-        copy.__parent__ = copy.__name__ = None
-        notify(ObjectCopiedEvent(copy, obj))
-
-        target[new_name] = copy
-        return new_name
-
-    def copyable(self):
-        """Returns True if the object is copyable, otherwise False."""
-        return True
-
-    def copyableTo(self, target, name=None):
-        """Say whether the object can be copied to the given `target`.
-
-        Returns ``True`` if it can be copied there. Otherwise, returns
-        ``False``.
-        """
-        if name is None:
-            name = self.context.__name__
-        try:
-            checkObject(target, name, self.context)
-        except Invalid:
-            return False
-        return True
-
-
-class ContainerItemRenamer(object):
-    """An IContainerItemRenamer adapter for containers.
-
-    This adapter uses IObjectMover to move an item within the same container
-    to a different name. We need to first setup an adapter for IObjectMover:
-
-      >>> from zope.container.interfaces import IContained
-      >>> gsm = zope.component.getGlobalSiteManager()
-      >>> gsm.registerAdapter(ObjectMover, (IContained, ), IObjectMover)
-
-    To rename an item in a container, instantiate a ContainerItemRenamer
-    with the container:
-
-      >>> container = SampleContainer()
-      >>> renamer = ContainerItemRenamer(container)
-
-    For this example, we'll rename an item 'foo':
-
-      >>> from zope.container.contained import Contained
-      >>> foo = Contained()
-      >>> container['foo'] = foo
-      >>> container['foo'] is foo
-      True
-
-    to 'bar':
-
-      >>> renamer.renameItem('foo', 'bar')
-      >>> container['foo'] is foo
-      Traceback (most recent call last):
-      KeyError: 'foo'
-      >>> container['bar'] is foo
-      True
-
-    If the item being renamed isn't in the container, a NotFoundError is raised:
-
-      >>> renamer.renameItem('foo', 'bar') # doctest:+ELLIPSIS
-      Traceback (most recent call last):
-      ItemNotFoundError: (<...SampleContainer...>, 'foo')
-
-    If the new item name already exists, a DuplicationError is raised:
-
-      >>> renamer.renameItem('bar', 'bar')
-      Traceback (most recent call last):
-      DuplicationError: bar is already in use
-
-    """
-
-    adapts(IContainer)
-
-    implements(IContainerItemRenamer)
-
-    def __init__(self, container):
-        self.container = container
-
-    def renameItem(self, oldName, newName):
-        object = self.container.get(oldName)
-        if object is None:
-            raise ItemNotFoundError(self.container, oldName)
-        mover = IObjectMover(object)
-
-        if newName in self.container:
-            raise DuplicationError("%s is already in use" % newName)
-
-        mover.moveTo(self.container, newName)
-
-
-class OrderedContainerItemRenamer(ContainerItemRenamer):
-    """Renames items within an ordered container.
-
-    This renamer preserves the original order of the contained items.
-
-    To illustrate, we need to setup an IObjectMover, which is used in the
-    renaming:
-
-      >>> from zope.container.interfaces import IContained
-      >>> gsm = zope.component.getGlobalSiteManager()
-      >>> gsm.registerAdapter(ObjectMover, (IContained, ), IObjectMover)
-
-    To rename an item in an ordered container, we instantiate a
-    OrderedContainerItemRenamer with the container:
-
-      >>> from zope.container.ordered import OrderedContainer
-      >>> container = OrderedContainer()
-      >>> renamer = OrderedContainerItemRenamer(container)
-
-    We'll add three items to the container:
-
-      >>> container['1'] = 'Item 1'
-      >>> container['2'] = 'Item 2'
-      >>> container['3'] = 'Item 3'
-      >>> container.items()
-      [('1', 'Item 1'), ('2', 'Item 2'), ('3', 'Item 3')]
-
-    When we rename one of the items:
-
-      >>> renamer.renameItem('1', 'I')
-
-    the order is preserved:
-
-      >>> container.items()
-      [('I', 'Item 1'), ('2', 'Item 2'), ('3', 'Item 3')]
-
-    Renaming the other two items also preserves the origina order:
-
-      >>> renamer.renameItem('2', 'II')
-      >>> renamer.renameItem('3', 'III')
-      >>> container.items()
-      [('I', 'Item 1'), ('II', 'Item 2'), ('III', 'Item 3')]
-
-    As with the standard renamer, trying to rename a non-existent item raises
-    an error:
-
-      >>> renamer.renameItem('IV', '4') # doctest:+ELLIPSIS
-      Traceback (most recent call last):
-      ItemNotFoundError: (<...OrderedContainer...>, 'IV')
-
-    And if the new item name already exists, a DuplicationError is raised:
-
-      >>> renamer.renameItem('III', 'I')
-      Traceback (most recent call last):
-      DuplicationError: I is already in use
-
-    """
-
-    adapts(IOrderedContainer)
-
-    implements(IContainerItemRenamer)
-
-    def renameItem(self, oldName, newName):
-        order = list(self.container.keys())
-        super(OrderedContainerItemRenamer, self).renameItem(oldName, newName)
-        order[order.index(oldName)] = newName
-        self.container.updateOrder(order)
-
-
-class PrincipalClipboard(object):
-    """Principal clipboard
-
-    Clipboard information consists of mappings of
-    ``{'action':action, 'target':target}``.
-    """
-
-    adapts(IAnnotations)
-
-    implements(IPrincipalClipboard)
-
-    def __init__(self, annotation):
-        self.context = annotation
-
-    def clearContents(self):
-        """Clear the contents of the clipboard"""
-        self.context['clipboard'] = ()
-
-    def addItems(self, action, targets):
-        """Add new items to the clipboard"""
-        contents = self.getContents()
-        actions = []
-        for target in targets:
-            actions.append({'action':action, 'target':target})
-        self.context['clipboard'] = contents + tuple(actions)
-
-    def setContents(self, clipboard):
-        """Replace the contents of the clipboard by the given value"""
-        self.context['clipboard'] = clipboard
-
-    def getContents(self):
-        """Return the contents of the clipboard"""
-        return self.context.get('clipboard', ())
-
-
-class ExampleContainer(SampleContainer):
-    # Sample container used for examples in doc stringss in this module
-
-    implements(INameChooser)
-
-    def chooseName(self, name, ob):
-       while name in self:
-          name += '_'
-       return name
-
-
-def dispatchToSublocations(object, event):
-    """Dispatches an event to sublocations of a given object.
-
-    This handler is used to dispatch copy events to sublocations.
-
-    To illustrate, we'll first create a hierarchy of objects:
-
-      >>> class L(object):
-      ...     def __init__(self, name):
-      ...         self.__name__ = name
-      ...         self.__parent__ = None
-      ...     def __repr__(self):
-      ...         return '%s(%s)' % (self.__class__.__name__, self.__name__)
-
-      >>> class C(L):
-      ...     implements(ISublocations)
-      ...     def __init__(self, name, *subs):
-      ...         L.__init__(self, name)
-      ...         self.subs = subs
-      ...         for sub in subs:
-      ...             sub.__parent__ = self
-      ...     def sublocations(self):
-      ...         return self.subs
-
-      >>> c = C(1,
-      ...       C(11,
-      ...         L(111),
-      ...         L(112),
-      ...         ),
-      ...       C(12,
-      ...         L(121),
-      ...         L(122),
-      ...         L(123),
-      ...         L(124),
-      ...         ),
-      ...       L(13),
-      ...       )
-
-    and a handler for copy events that records the objects it's seen:
-
-      >>> seen = []
-      >>> def handler(ob, event):
-      ...     seen.append((ob, event.object))
-
-    Finally, we need to register our handler for copy events:
-
-      >>> from zope.lifecycleevent.interfaces import IObjectCopiedEvent
-      >>> gsm = zope.component.getGlobalSiteManager()
-      >>> gsm.registerHandler(handler, [None, IObjectCopiedEvent])
-
-    and this function as a dispatcher:
-
-      >>> gsm.registerHandler(dispatchToSublocations,
-      ...                     [None, IObjectCopiedEvent])
-
-    When we notify that our root object has been copied:
-
-      >>> notify(ObjectCopiedEvent(c, L('')))
-
-    we see that our handler has seen all of the subobjects:
-
-      >>> seenreprs = map(repr, seen)
-      >>> seenreprs.sort()
-      >>> seenreprs #doctest: +NORMALIZE_WHITESPACE
-      ['(C(1), C(1))', '(C(11), C(1))', '(C(12), C(1))',
-       '(L(111), C(1))', '(L(112), C(1))', '(L(121), C(1))',
-       '(L(122), C(1))', '(L(123), C(1))', '(L(124), C(1))',
-       '(L(13), C(1))']
-    """
-    subs = ISublocations(object, None)
-    if subs is not None:
-        for sub in subs.sublocations():
-            for ignored in zope.component.subscribers((sub, event), None):
-                pass # They do work in the adapter fetch

Copied: zope.copypastemove/tags/3.5.1/src/zope/copypastemove/__init__.py (from rev 96287, zope.copypastemove/trunk/src/zope/copypastemove/__init__.py)
===================================================================
--- zope.copypastemove/tags/3.5.1/src/zope/copypastemove/__init__.py	                        (rev 0)
+++ zope.copypastemove/tags/3.5.1/src/zope/copypastemove/__init__.py	2009-02-08 23:03:23 UTC (rev 96289)
@@ -0,0 +1,675 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Copy, Paste and Move support for content components
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+import zope.component
+from zope.interface import implements, Invalid
+from zope.exceptions import DuplicationError
+from zope.component import adapts
+from zope.copy import copy
+from zope.event import notify
+from zope.location.interfaces import ISublocations
+from zope.annotation.interfaces import IAnnotations
+from zope.annotation.interfaces import IAnnotations
+from zope.lifecycleevent import ObjectCopiedEvent
+
+from zope.copypastemove.interfaces import IObjectMover
+from zope.copypastemove.interfaces import IObjectCopier
+from zope.copypastemove.interfaces import IContainerItemRenamer
+from zope.copypastemove.interfaces import IPrincipalClipboard
+from zope.copypastemove.interfaces import ItemNotFoundError
+
+from zope.container.sample import SampleContainer
+from zope.container.interfaces import IContainer, IOrderedContainer
+from zope.container.interfaces import IContained
+from zope.container.interfaces import INameChooser
+from zope.container.constraints import checkObject
+
+class ObjectMover(object):
+    """Adapter for moving objects between containers
+
+    To use an object mover, pass a contained `object` to the class.
+    The contained `object` should implement `IContained`.  It should be
+    contained in a container that has an adapter to `INameChooser`.
+
+
+    >>> from zope.container.contained import Contained
+    >>> ob = Contained()
+    >>> container = ExampleContainer()
+    >>> container[u'foo'] = ob
+    >>> mover = ObjectMover(ob)
+
+    In addition to moving objects, object movers can tell you if the
+    object is movable:
+
+    >>> mover.moveable()
+    True
+
+    which, at least for now, they always are.  A better question to
+    ask is whether we can move to a particular container. Right now,
+    we can always move to a container of the same class:
+
+    >>> container2 = ExampleContainer()
+    >>> mover.moveableTo(container2)
+    True
+    >>> mover.moveableTo({})
+    Traceback (most recent call last):
+    ...
+    TypeError: Container is not a valid Zope container.
+
+    Of course, once we've decided we can move an object, we can use
+    the mover to do so:
+
+    >>> mover.moveTo(container2)
+    u'foo'
+    >>> list(container)
+    []
+    >>> list(container2)
+    [u'foo']
+    >>> ob.__parent__ is container2
+    True
+
+    We can also specify a name:
+
+    >>> mover.moveTo(container2, u'bar')
+    u'bar'
+    >>> list(container2)
+    [u'bar']
+    >>> ob.__parent__ is container2
+    True
+    >>> ob.__name__
+    u'bar'
+
+    But we may not use the same name given, if the name is already in
+    use:
+
+    >>> container2[u'splat'] = 1
+    >>> mover.moveTo(container2, u'splat')
+    u'splat_'
+    >>> l = list(container2)
+    >>> l.sort()
+    >>> l
+    [u'splat', u'splat_']
+    >>> ob.__name__
+    u'splat_'
+
+
+    If we try to move to an invalid container, we'll get an error:
+
+    >>> mover.moveTo({})
+    Traceback (most recent call last):
+    ...
+    TypeError: Container is not a valid Zope container.
+
+
+    Do a test for preconditions:
+
+    >>> import zope.interface
+    >>> import zope.schema
+    >>> def preNoZ(container, name, ob):
+    ...     "Silly precondition example"
+    ...     if name.startswith("Z"):
+    ...         raise zope.interface.Invalid("Invalid name.")
+
+    >>> class I1(zope.interface.Interface):
+    ...     def __setitem__(name, on):
+    ...         "Add an item"
+    ...     __setitem__.precondition = preNoZ
+
+    >>> from zope.container.interfaces import IContainer
+    >>> class C1(object):
+    ...     zope.interface.implements(I1, IContainer)
+    ...     def __repr__(self):
+    ...         return 'C1'
+
+    >>> from zope.container.constraints import checkObject
+    >>> container3 = C1()
+    >>> mover.moveableTo(container3, 'ZDummy')
+    False
+    >>> mover.moveableTo(container3, 'newName')
+    True
+
+    And a test for constraints:
+
+    >>> def con1(container):
+    ...     "silly container constraint"
+    ...     if not hasattr(container, 'x'):
+    ...         return False
+    ...     return True
+    ...
+    >>> class I2(zope.interface.Interface):
+    ...     __parent__ = zope.schema.Field(constraint=con1)
+    ...
+    >>> class constrainedObject(object):
+    ...     zope.interface.implements(I2)
+    ...     def __init__(self):
+    ...         self.__name__ = 'constrainedObject'
+    ...
+    >>> cO = constrainedObject()
+    >>> mover2 = ObjectMover(cO)
+    >>> mover2.moveableTo(container)
+    False
+    >>> container.x = 1
+    >>> mover2.moveableTo(container)
+    True
+
+    """
+
+    adapts(IContained)
+
+    implements(IObjectMover)
+
+    def __init__(self, object):
+        self.context = object
+        self.__parent__ = object # TODO: see if we can automate this
+
+    def moveTo(self, target, new_name=None):
+        """Move this object to the `target` given.
+
+        Returns the new name within the `target`
+        Typically, the `target` is adapted to `IPasteTarget`."""
+
+        obj = self.context
+        container = obj.__parent__
+
+        orig_name = obj.__name__
+        if new_name is None:
+            new_name = orig_name
+
+        checkObject(target, new_name, obj)
+
+        if target is container and new_name == orig_name:
+            # Nothing to do
+            return
+
+        chooser = INameChooser(target)
+        new_name = chooser.chooseName(new_name, obj)
+
+        target[new_name] = obj
+        del container[orig_name]
+        return new_name
+
+    def moveable(self):
+        """Returns ``True`` if the object is moveable, otherwise ``False``."""
+        return True
+
+    def moveableTo(self, target, name=None):
+        """Say whether the object can be moved to the given target.
+
+        Returns ``True`` if it can be moved there. Otherwise, returns
+        ``False``.
+        """
+        if name is None:
+            name = self.context.__name__
+        try:
+            checkObject(target, name, self.context)
+        except Invalid:
+            return False
+        return True
+
+class ObjectCopier(object):
+    """Adapter for copying objects between containers
+
+    To use an object copier, pass a contained `object` to the class.
+    The contained `object` should implement `IContained`.  It should be
+    contained in a container that has an adapter to `INameChooser`.
+
+    >>> from zope.container.contained import Contained
+    >>> ob = Contained()
+    >>> container = ExampleContainer()
+    >>> container[u'foo'] = ob
+    >>> copier = ObjectCopier(ob)
+
+    In addition to moving objects, object copiers can tell you if the
+    object is movable:
+
+    >>> copier.copyable()
+    True
+
+    which, at least for now, they always are.  A better question to
+    ask is whether we can copy to a particular container. Right now,
+    we can always copy to a container of the same class:
+
+    >>> container2 = ExampleContainer()
+    >>> copier.copyableTo(container2)
+    True
+    >>> copier.copyableTo({})
+    Traceback (most recent call last):
+    ...
+    TypeError: Container is not a valid Zope container.
+
+    Of course, once we've decided we can copy an object, we can use
+    the copier to do so:
+
+    >>> copier.copyTo(container2)
+    u'foo'
+    >>> list(container)
+    [u'foo']
+    >>> list(container2)
+    [u'foo']
+    >>> ob.__parent__ is container
+    True
+    >>> container2[u'foo'] is ob
+    False
+    >>> container2[u'foo'].__parent__ is container2
+    True
+    >>> container2[u'foo'].__name__
+    u'foo'
+
+    We can also specify a name:
+
+    >>> copier.copyTo(container2, u'bar')
+    u'bar'
+    >>> l = list(container2)
+    >>> l.sort()
+    >>> l
+    [u'bar', u'foo']
+
+    >>> ob.__parent__ is container
+    True
+    >>> container2[u'bar'] is ob
+    False
+    >>> container2[u'bar'].__parent__ is container2
+    True
+    >>> container2[u'bar'].__name__
+    u'bar'
+
+    But we may not use the same name given, if the name is already in
+    use:
+
+    >>> copier.copyTo(container2, u'bar')
+    u'bar_'
+    >>> l = list(container2)
+    >>> l.sort()
+    >>> l
+    [u'bar', u'bar_', u'foo']
+    >>> container2[u'bar_'].__name__
+    u'bar_'
+
+
+    If we try to copy to an invalid container, we'll get an error:
+
+    >>> copier.copyTo({})
+    Traceback (most recent call last):
+    ...
+    TypeError: Container is not a valid Zope container.
+
+    Do a test for preconditions:
+
+    >>> import zope.interface
+    >>> import zope.schema
+    >>> def preNoZ(container, name, ob):
+    ...     "Silly precondition example"
+    ...     if name.startswith("Z"):
+    ...         raise zope.interface.Invalid("Invalid name.")
+
+    >>> class I1(zope.interface.Interface):
+    ...     def __setitem__(name, on):
+    ...         "Add an item"
+    ...     __setitem__.precondition = preNoZ
+
+    >>> from zope.container.interfaces import IContainer
+    >>> class C1(object):
+    ...     zope.interface.implements(I1, IContainer)
+    ...     def __repr__(self):
+    ...         return 'C1'
+
+    >>> from zope.container.constraints import checkObject
+    >>> container3 = C1()
+    >>> copier.copyableTo(container3, 'ZDummy')
+    False
+    >>> copier.copyableTo(container3, 'newName')
+    True
+
+    And a test for constraints:
+
+    >>> def con1(container):
+    ...     "silly container constraint"
+    ...     if not hasattr(container, 'x'):
+    ...         return False
+    ...     return True
+    ...
+    >>> class I2(zope.interface.Interface):
+    ...     __parent__ = zope.schema.Field(constraint=con1)
+    ...
+    >>> class constrainedObject(object):
+    ...     zope.interface.implements(I2)
+    ...     def __init__(self):
+    ...         self.__name__ = 'constrainedObject'
+    ...
+    >>> cO = constrainedObject()
+    >>> copier2 = ObjectCopier(cO)
+    >>> copier2.copyableTo(container)
+    False
+    >>> container.x = 1
+    >>> copier2.copyableTo(container)
+    True
+
+    """
+
+    adapts(IContained)
+
+    implements(IObjectCopier)
+
+    def __init__(self, object):
+        self.context = object
+        self.__parent__ = object # TODO: see if we can automate this
+
+    def copyTo(self, target, new_name=None):
+        """Copy this object to the `target` given.
+
+        Returns the new name within the `target`.
+
+        Typically, the `target` is adapted to `IPasteTarget`.
+        After the copy is added to the `target` container, publish
+        an `IObjectCopied` event in the context of the target container.
+        If a new object is created as part of the copying process, then
+        an `IObjectCreated` event should be published.
+        """
+        obj = self.context
+        container = obj.__parent__
+
+        orig_name = obj.__name__
+        if new_name is None:
+            new_name = orig_name
+
+        checkObject(target, new_name, obj)
+
+        chooser = INameChooser(target)
+        new_name = chooser.chooseName(new_name, obj)
+
+        new = copy(obj)
+        notify(ObjectCopiedEvent(new, obj))
+
+        target[new_name] = new
+        return new_name
+
+    def copyable(self):
+        """Returns True if the object is copyable, otherwise False."""
+        return True
+
+    def copyableTo(self, target, name=None):
+        """Say whether the object can be copied to the given `target`.
+
+        Returns ``True`` if it can be copied there. Otherwise, returns
+        ``False``.
+        """
+        if name is None:
+            name = self.context.__name__
+        try:
+            checkObject(target, name, self.context)
+        except Invalid:
+            return False
+        return True
+
+
+class ContainerItemRenamer(object):
+    """An IContainerItemRenamer adapter for containers.
+
+    This adapter uses IObjectMover to move an item within the same container
+    to a different name. We need to first setup an adapter for IObjectMover:
+
+      >>> from zope.container.interfaces import IContained
+      >>> gsm = zope.component.getGlobalSiteManager()
+      >>> gsm.registerAdapter(ObjectMover, (IContained, ), IObjectMover)
+
+    To rename an item in a container, instantiate a ContainerItemRenamer
+    with the container:
+
+      >>> container = SampleContainer()
+      >>> renamer = ContainerItemRenamer(container)
+
+    For this example, we'll rename an item 'foo':
+
+      >>> from zope.container.contained import Contained
+      >>> foo = Contained()
+      >>> container['foo'] = foo
+      >>> container['foo'] is foo
+      True
+
+    to 'bar':
+
+      >>> renamer.renameItem('foo', 'bar')
+      >>> container['foo'] is foo
+      Traceback (most recent call last):
+      KeyError: 'foo'
+      >>> container['bar'] is foo
+      True
+
+    If the item being renamed isn't in the container, a NotFoundError is raised:
+
+      >>> renamer.renameItem('foo', 'bar') # doctest:+ELLIPSIS
+      Traceback (most recent call last):
+      ItemNotFoundError: (<...SampleContainer...>, 'foo')
+
+    If the new item name already exists, a DuplicationError is raised:
+
+      >>> renamer.renameItem('bar', 'bar')
+      Traceback (most recent call last):
+      DuplicationError: bar is already in use
+
+    """
+
+    adapts(IContainer)
+
+    implements(IContainerItemRenamer)
+
+    def __init__(self, container):
+        self.container = container
+
+    def renameItem(self, oldName, newName):
+        object = self.container.get(oldName)
+        if object is None:
+            raise ItemNotFoundError(self.container, oldName)
+        mover = IObjectMover(object)
+
+        if newName in self.container:
+            raise DuplicationError("%s is already in use" % newName)
+
+        mover.moveTo(self.container, newName)
+
+
+class OrderedContainerItemRenamer(ContainerItemRenamer):
+    """Renames items within an ordered container.
+
+    This renamer preserves the original order of the contained items.
+
+    To illustrate, we need to setup an IObjectMover, which is used in the
+    renaming:
+
+      >>> from zope.container.interfaces import IContained
+      >>> gsm = zope.component.getGlobalSiteManager()
+      >>> gsm.registerAdapter(ObjectMover, (IContained, ), IObjectMover)
+
+    To rename an item in an ordered container, we instantiate a
+    OrderedContainerItemRenamer with the container:
+
+      >>> from zope.container.ordered import OrderedContainer
+      >>> container = OrderedContainer()
+      >>> renamer = OrderedContainerItemRenamer(container)
+
+    We'll add three items to the container:
+
+      >>> container['1'] = 'Item 1'
+      >>> container['2'] = 'Item 2'
+      >>> container['3'] = 'Item 3'
+      >>> container.items()
+      [('1', 'Item 1'), ('2', 'Item 2'), ('3', 'Item 3')]
+
+    When we rename one of the items:
+
+      >>> renamer.renameItem('1', 'I')
+
+    the order is preserved:
+
+      >>> container.items()
+      [('I', 'Item 1'), ('2', 'Item 2'), ('3', 'Item 3')]
+
+    Renaming the other two items also preserves the origina order:
+
+      >>> renamer.renameItem('2', 'II')
+      >>> renamer.renameItem('3', 'III')
+      >>> container.items()
+      [('I', 'Item 1'), ('II', 'Item 2'), ('III', 'Item 3')]
+
+    As with the standard renamer, trying to rename a non-existent item raises
+    an error:
+
+      >>> renamer.renameItem('IV', '4') # doctest:+ELLIPSIS
+      Traceback (most recent call last):
+      ItemNotFoundError: (<...OrderedContainer...>, 'IV')
+
+    And if the new item name already exists, a DuplicationError is raised:
+
+      >>> renamer.renameItem('III', 'I')
+      Traceback (most recent call last):
+      DuplicationError: I is already in use
+
+    """
+
+    adapts(IOrderedContainer)
+
+    implements(IContainerItemRenamer)
+
+    def renameItem(self, oldName, newName):
+        order = list(self.container.keys())
+        super(OrderedContainerItemRenamer, self).renameItem(oldName, newName)
+        order[order.index(oldName)] = newName
+        self.container.updateOrder(order)
+
+
+class PrincipalClipboard(object):
+    """Principal clipboard
+
+    Clipboard information consists of mappings of
+    ``{'action':action, 'target':target}``.
+    """
+
+    adapts(IAnnotations)
+
+    implements(IPrincipalClipboard)
+
+    def __init__(self, annotation):
+        self.context = annotation
+
+    def clearContents(self):
+        """Clear the contents of the clipboard"""
+        self.context['clipboard'] = ()
+
+    def addItems(self, action, targets):
+        """Add new items to the clipboard"""
+        contents = self.getContents()
+        actions = []
+        for target in targets:
+            actions.append({'action':action, 'target':target})
+        self.context['clipboard'] = contents + tuple(actions)
+
+    def setContents(self, clipboard):
+        """Replace the contents of the clipboard by the given value"""
+        self.context['clipboard'] = clipboard
+
+    def getContents(self):
+        """Return the contents of the clipboard"""
+        return self.context.get('clipboard', ())
+
+
+class ExampleContainer(SampleContainer):
+    # Sample container used for examples in doc stringss in this module
+
+    implements(INameChooser)
+
+    def chooseName(self, name, ob):
+       while name in self:
+          name += '_'
+       return name
+
+
+def dispatchToSublocations(object, event):
+    """Dispatches an event to sublocations of a given object.
+
+    This handler is used to dispatch copy events to sublocations.
+
+    To illustrate, we'll first create a hierarchy of objects:
+
+      >>> class L(object):
+      ...     def __init__(self, name):
+      ...         self.__name__ = name
+      ...         self.__parent__ = None
+      ...     def __repr__(self):
+      ...         return '%s(%s)' % (self.__class__.__name__, self.__name__)
+
+      >>> class C(L):
+      ...     implements(ISublocations)
+      ...     def __init__(self, name, *subs):
+      ...         L.__init__(self, name)
+      ...         self.subs = subs
+      ...         for sub in subs:
+      ...             sub.__parent__ = self
+      ...     def sublocations(self):
+      ...         return self.subs
+
+      >>> c = C(1,
+      ...       C(11,
+      ...         L(111),
+      ...         L(112),
+      ...         ),
+      ...       C(12,
+      ...         L(121),
+      ...         L(122),
+      ...         L(123),
+      ...         L(124),
+      ...         ),
+      ...       L(13),
+      ...       )
+
+    and a handler for copy events that records the objects it's seen:
+
+      >>> seen = []
+      >>> def handler(ob, event):
+      ...     seen.append((ob, event.object))
+
+    Finally, we need to register our handler for copy events:
+
+      >>> from zope.lifecycleevent.interfaces import IObjectCopiedEvent
+      >>> gsm = zope.component.getGlobalSiteManager()
+      >>> gsm.registerHandler(handler, [None, IObjectCopiedEvent])
+
+    and this function as a dispatcher:
+
+      >>> gsm.registerHandler(dispatchToSublocations,
+      ...                     [None, IObjectCopiedEvent])
+
+    When we notify that our root object has been copied:
+
+      >>> notify(ObjectCopiedEvent(c, L('')))
+
+    we see that our handler has seen all of the subobjects:
+
+      >>> seenreprs = map(repr, seen)
+      >>> seenreprs.sort()
+      >>> seenreprs #doctest: +NORMALIZE_WHITESPACE
+      ['(C(1), C(1))', '(C(11), C(1))', '(C(12), C(1))',
+       '(L(111), C(1))', '(L(112), C(1))', '(L(121), C(1))',
+       '(L(122), C(1))', '(L(123), C(1))', '(L(124), C(1))',
+       '(L(13), C(1))']
+    """
+    subs = ISublocations(object, None)
+    if subs is not None:
+        for sub in subs.sublocations():
+            for ignored in zope.component.subscribers((sub, event), None):
+                pass # They do work in the adapter fetch

Deleted: zope.copypastemove/tags/3.5.1/src/zope/copypastemove/interfaces.py
===================================================================
--- zope.copypastemove/trunk/src/zope/copypastemove/interfaces.py	2009-02-08 17:03:40 UTC (rev 96257)
+++ zope.copypastemove/tags/3.5.1/src/zope/copypastemove/interfaces.py	2009-02-08 23:03:23 UTC (rev 96289)
@@ -1,95 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (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.
-#
-##############################################################################
-"""Copy and Move support
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-from zope.interface import Interface
-
-class IObjectMover(Interface):
-    """Use `IObjectMover(obj)` to move an object somewhere."""
-
-    def moveTo(target, new_name=None):
-        """Move this object to the target given.
-
-        Returns the new name within the target.
-        Typically, the target is adapted to `IPasteTarget`."""
-
-    def moveable():
-        """Returns ``True`` if the object is moveable, otherwise ``False``."""
-
-    def moveableTo(target, name=None):
-        """Say whether the object can be moved to the given `target`.
-
-        Returns ``True`` if it can be moved there. Otherwise, returns
-        ``False``.
-        """
-
-class IObjectCopier(Interface):
-
-    def copyTo(target, new_name=None):
-        """Copy this object to the `target` given.
-
-        Returns the new name within the `target`.
-        Typically, the target is adapted to `IPasteTarget`.
-        After the copy is added to the target container, publish
-        an `IObjectCopied` event in the context of the target container.
-        If a new object is created as part of the copying process, then
-        an `IObjectCreated` event should be published.
-        """
-
-    def copyable():
-        """Returns ``True`` if the object is copyable, otherwise ``False``."""
-
-    def copyableTo(target, name=None):
-        """Say whether the object can be copied to the given `target`.
-
-        Returns ``True`` if it can be copied there. Otherwise, returns
-        ``False``.
-        """
-
-class IContainerItemRenamer(Interface):
-
-    def renameItem(oldName, newName):
-        """Renames an object in the container from oldName to newName.
-
-        Raises ItemNotFoundError if oldName doesn't exist in the container.
-
-        Raises DuplicationError if newName is already used in the container.
-        """
-
-class IPrincipalClipboard(Interface):
-    """Interface for adapters that store/retrieve clipboard information
-    for a principal.
-
-    Clipboard information consists of mappings of
-      ``{'action':action, 'target':target}``.
-    """
-
-    def clearContents():
-        """Clear the contents of the clipboard"""
-
-    def addItems(action, targets):
-        """Add new items to the clipboard"""
-
-    def setContents(clipboard):
-        """Replace the contents of the clipboard by the given value"""
-
-    def getContents():
-        """Return the contents of the clipboard"""
-
-class IItemNotFoundError(Interface):
-    pass

Copied: zope.copypastemove/tags/3.5.1/src/zope/copypastemove/interfaces.py (from rev 96287, zope.copypastemove/trunk/src/zope/copypastemove/interfaces.py)
===================================================================
--- zope.copypastemove/tags/3.5.1/src/zope/copypastemove/interfaces.py	                        (rev 0)
+++ zope.copypastemove/tags/3.5.1/src/zope/copypastemove/interfaces.py	2009-02-08 23:03:23 UTC (rev 96289)
@@ -0,0 +1,98 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Copy and Move support
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+from zope.interface import Interface, implements
+
+class IObjectMover(Interface):
+    """Use `IObjectMover(obj)` to move an object somewhere."""
+
+    def moveTo(target, new_name=None):
+        """Move this object to the target given.
+
+        Returns the new name within the target.
+        Typically, the target is adapted to `IPasteTarget`."""
+
+    def moveable():
+        """Returns ``True`` if the object is moveable, otherwise ``False``."""
+
+    def moveableTo(target, name=None):
+        """Say whether the object can be moved to the given `target`.
+
+        Returns ``True`` if it can be moved there. Otherwise, returns
+        ``False``.
+        """
+
+class IObjectCopier(Interface):
+
+    def copyTo(target, new_name=None):
+        """Copy this object to the `target` given.
+
+        Returns the new name within the `target`.
+        Typically, the target is adapted to `IPasteTarget`.
+        After the copy is added to the target container, publish
+        an `IObjectCopied` event in the context of the target container.
+        If a new object is created as part of the copying process, then
+        an `IObjectCreated` event should be published.
+        """
+
+    def copyable():
+        """Returns ``True`` if the object is copyable, otherwise ``False``."""
+
+    def copyableTo(target, name=None):
+        """Say whether the object can be copied to the given `target`.
+
+        Returns ``True`` if it can be copied there. Otherwise, returns
+        ``False``.
+        """
+
+class IContainerItemRenamer(Interface):
+
+    def renameItem(oldName, newName):
+        """Renames an object in the container from oldName to newName.
+
+        Raises ItemNotFoundError if oldName doesn't exist in the container.
+
+        Raises DuplicationError if newName is already used in the container.
+        """
+
+class IPrincipalClipboard(Interface):
+    """Interface for adapters that store/retrieve clipboard information
+    for a principal.
+
+    Clipboard information consists of mappings of
+      ``{'action':action, 'target':target}``.
+    """
+
+    def clearContents():
+        """Clear the contents of the clipboard"""
+
+    def addItems(action, targets):
+        """Add new items to the clipboard"""
+
+    def setContents(clipboard):
+        """Replace the contents of the clipboard by the given value"""
+
+    def getContents():
+        """Return the contents of the clipboard"""
+
+class IItemNotFoundError(Interface):
+    pass
+
+class ItemNotFoundError(LookupError):
+    implements(IItemNotFoundError)



More information about the Checkins mailing list