[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/ Added a copier for reigsterable objects that removes registered usages for the copy.

Garrett Smith garrett at mojave-corp.com
Wed Jul 7 19:58:59 EDT 2004


Log message for revision 26197:
Added a copier for reigsterable objects that removes registered usages for the copy.

This resolves http://collector.zope.org/Zope3-dev/220


-=-
Modified: Zope3/trunk/src/zope/app/copypastemove/__init__.py
===================================================================
--- Zope3/trunk/src/zope/app/copypastemove/__init__.py	2004-07-07 23:17:29 UTC (rev 26196)
+++ Zope3/trunk/src/zope/app/copypastemove/__init__.py	2004-07-07 23:58:59 UTC (rev 26197)
@@ -373,11 +373,23 @@
 
         copy = removeAllProxies(obj)
         copy = locationCopy(copy)
-        copy.__parent__ = copy.__name__ = None
+        self._configureCopy(copy, target, new_name)
         notify(ObjectCopiedEvent(copy))
 
         target[new_name] = copy
 
+    def _configureCopy(self, copy, target, new_name):
+        """Configures the copied object before it is added to target.
+        
+        target and new_name are provided as additional information.
+        
+        By default, copy.__parent__ and copy.__name__ are set to None.
+        
+        Subclasses may override this method to perform additional
+        configuration of the copied object.
+        """
+        copy.__parent__ = copy.__name__ = None
+
     def copyable(self):
         '''Returns True if the object is copyable, otherwise False.'''
         return True

Modified: Zope3/trunk/src/zope/app/registration/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/registration/configure.zcml	2004-07-07 23:17:29 UTC (rev 26196)
+++ Zope3/trunk/src/zope/app/registration/configure.zcml	2004-07-07 23:58:59 UTC (rev 26197)
@@ -16,7 +16,14 @@
     provides=".interfaces.IRegistered"
     factory=".registration.Registered"
     />
-  
+    
+  <adapter
+    for=".interfaces.IRegisterable"
+    provides="zope.app.copypastemove.interfaces.IObjectCopier"
+    factory=".registration.RegisterableCopier"
+    permission="zope.ManageContent"
+    />
+
   <!-- Registration Manager -->
 
   <content class=".registration.RegistrationManager">

Modified: Zope3/trunk/src/zope/app/registration/registration.py
===================================================================
--- Zope3/trunk/src/zope/app/registration/registration.py	2004-07-07 23:17:29 UTC (rev 26196)
+++ Zope3/trunk/src/zope/app/registration/registration.py	2004-07-07 23:58:59 UTC (rev 26197)
@@ -29,6 +29,7 @@
 from zope.app.annotation.interfaces import IAttributeAnnotatable
 from zope.app.container.contained import Contained
 from zope.app.container.contained import setitem, contained, uncontained
+from zope.app.copypastemove import ObjectCopier
 from zope.app.dependable.interfaces import IDependable, DependencyError
 from zope.app.component.localservice import getLocalServices
 from zope.app.location import inside
@@ -651,7 +652,7 @@
     """Updates componentPath for registrations on component rename."""
     if event.oldParent is not None and event.newParent is not None:
         if event.oldParent is event.newParent:
-            registered = interfaces.IRegistered(registerable)
+            registered = interfaces.IRegistered(registerable, None)
             if registered is not None:
                 for reg in registered.registrations():
                     if interfaces.IComponentRegistration.providedBy(reg):
@@ -670,6 +671,8 @@
     """
     implements(interfaces.IRegistered)
 
+    __used_for__ = interfaces.IRegisterable
+
     # We want to use this key:
     #   key = "zope.app.registration.Registered"
     # But we have existing annotations with the following key, so we'll keep
@@ -684,6 +687,21 @@
         return [zapi.traverse(self.context, path)
                 for path in self.getPaths()]
 
+class RegisterableCopier(ObjectCopier):
+    """Copies registerable components.
+
+    Performs the additional step of removing existing registered usages
+    for the new copy.
+    """
+    __used_for__ = interfaces.IRegisterable
+
+    def _configureCopy(self, copy, target, new_name):
+        ObjectCopier._configureCopy(self, copy, target, new_name)
+        registered = interfaces.IRegistered(copy, None)
+        if registered is not None:
+            for usage in registered.usages():
+                registered.removeUsage(usage)
+
 class RegistrationManager(Persistent, Contained):
     """Registration manager
 

Modified: Zope3/trunk/src/zope/app/registration/tests/test_registrations.py
===================================================================
--- Zope3/trunk/src/zope/app/registration/tests/test_registrations.py	2004-07-07 23:17:29 UTC (rev 26196)
+++ Zope3/trunk/src/zope/app/registration/tests/test_registrations.py	2004-07-07 23:58:59 UTC (rev 26197)
@@ -43,6 +43,7 @@
     ComponentRegistrationAddSubscriber, \
     RegisterableMoveSubscriber
 from zope.app.registration.registration import Registered
+from zope.app.registration.registration import RegisterableCopier
 from zope.app.traversing.interfaces import IPhysicallyLocatable
 import zope.interface
 from zope.app.annotation.interfaces import IAnnotations
@@ -212,18 +213,18 @@
 class TestRegisterableEvents:
     """Tests handling of registered component rename.
 
-    >>> PlacefulSetup().setUp()
+    >>> sm = PlacefulSetup().setUp(site=True)
 
-    We'll first add a registerable component to the root folder:
+    We'll first add a registerable component to the default site management
+    folder:
 
-        >>> rootFolder = PlacefulSetup().rootFolder
         >>> component = DummyRegisterable()
-        >>> rootFolder['foo'] = component
+        >>> sm['default']['foo'] = component
 
     and create a registration for it:
 
         >>> reg = ComponentRegistration("foo")
-        >>> rootFolder['reg'] = reg
+        >>> sm['default']['reg'] = reg
         >>> ztapi.provideAdapter(IRegisterable, IRegistered, Registered)
         >>> IRegistered(component).addUsage('reg')
 
@@ -237,9 +238,9 @@
     (i.e. oldParent is the same as newParent):
 
         >>> event = ObjectMovedEvent(component,
-        ...     oldParent=rootFolder,
+        ...     oldParent=sm['default'],
         ...     oldName='foo',
-        ...     newParent=rootFolder,
+        ...     newParent=sm['default'],
         ...     newName='bar')
         >>> RegisterableMoveSubscriber(component, event)
 
@@ -252,7 +253,7 @@
     oldParent is different from newParent):
 
         >>> event = ObjectMovedEvent(component,
-        ...     oldParent=rootFolder,
+        ...     oldParent=sm['default'],
         ...     oldName='foo',
         ...     newParent=object(),
         ...     newName='foo')
@@ -263,6 +264,50 @@
     >>> PlacefulSetup().tearDown()
     """
 
+class TestRegisterableCopier:
+    """Tests the copier for registerable components.
+
+    >>> sm = PlacefulSetup().setUp(site=True)
+
+    Registered components have annotation noting which registrations are
+    currently using the component. Copied components should not be noted
+    as used.
+
+    RegisterableCopier is used instead of the default object copier to
+    ensure that such usages are removed from the copied component.
+
+    To illustrate, we'll setup a component in the default site management
+    folder:
+
+        >>> component = DummyRegisterable()
+        >>> sm['default']['foo'] = component
+
+    and create a registration for it:
+
+        >>> reg = ComponentRegistration("foo")
+        >>> sm['default']['reg'] = reg
+        >>> ztapi.provideAdapter(IRegisterable, IRegistered, Registered)
+        >>> IRegistered(component).addUsage('/++etc++site/default/reg')
+
+    Note the current usages for the component:
+
+        >>> IRegistered(component).usages()
+        (u'/++etc++site/default/reg',)
+
+    Using RegisterableCopier, we can make a copy of the component:
+
+        >>> copier = RegisterableCopier(component)
+        >>> copier.copyTo(sm['default'], 'bar')
+
+    The copied component is not used:
+
+        >>> copy = sm['default']['bar']
+        >>> IRegistered(copy).usages()
+        ()
+
+    >>> PlacefulSetup().tearDown()
+    """
+
 def test_suite():
     import sys
     return TestSuite((



More information about the Zope3-Checkins mailing list