[Zope3-Users] Re: Renaming and OrderedContainer

jürgen Kartnaller j.kartnaller at cable.vol.at
Mon Jan 31 14:19:25 EST 2005


Hi Garret,
here are the files from copypastemove

__init__.py
configure.zcml
tests.test_rename.py

zope.app.container.ordered.py
zope.app.container.configure.zcml
zope.app.container.test.test_ordered.py

Jürgen

Garrett Smith wrote:
> Jürgen, 
> 
> I think adapting the container to IObjectRenamer is the right thing.
> 
> Just reply to this with your new/modified files.
> 
> The tests should end up looking like those for ObjectMover and
> ObjectCopier. I'd encourage you to give it a try -- there's a learning
> curve, but you may find it as rewarding as writing adapters :) In any
> event, we'll have to have them before committing to the trunk. (I'll
> help if you need it.)
> 
>  -- Garrett
> 
> jürgen Kartnaller wrote:
> 
>>Garrett Smith wrote:
>>
>>>jürgen Kartnaller wrote:
>>>
>>>
>>>>Hello all,
>>>>I found the following problem when renaming objects :
>>>>
>>>>zope.app.copypastemove.rename uses the ObjectMover to rename an
>>>>object within a container. There is no problem as long as you are
>>>>using BTree containers. 
>>>>
>>>>If rename is used on an OrderedContainer then the object is moved to
>>>>the end of the list because ObjectMover first adds the object with
>>>>the new name to the container (OrderedContainer puts the new object
>>>>to the end of the list) and then deletes the old name.
>>>>
>>>>To solve this problem a container should have a rename function !
>>>
>>>
>>>The problem is that copypastemove.rename doesn't use something like
>>>IObjectRenamer. The default implementation of rename works fine for
>>>normal containers, but not for ordered containers.
>>>
>>>This would be straight forward to implement, if you're iterested :)
>>
>>Of course it is, even for a zope3 newbie like me
>>I added an IObjectRenamer (see below)
>>
>>
>>>A 'rename' method isn't z3onic (pronounced zee-thronic? ;) We like to
>>>tack on new functionality using the component patterns, which have
>>>some nice advantages over polymorphic methods.
>>
>>Right, with this implementation I got the understanding of adapters.
>>
>>
>>I added IObjectRenamer, implemented an ObjectRenamer (which is doing
>>the same than the ObjectMover but only within one container).
>>
>>What I found is :
>>I need to implement an adapter for OrderedContainer.
>>The problem now is, that I need to adapt to the container and not to
>>the object I want to rename.
>>IObjectMover and IObjectCopier are adapting to the object not to the
>>container, which is ok for this case.
>>For renaming I need to differentiate between different behavior of the
>>container and not the object.
>>So for IObjectRenamer I need to adapt to the container.
>>
>>Is this right ?
>>
>>I implemented OrderedContainerObjectRenamer as adapter for
>>OrderedContainer. 
>>
>>I love this adapter thing !!!
>>
>>My question is now : (for my understanding of adapters)
>>
>>Is an adapter allowed to do everything on the class it adapts ?
>>I mean, should it only use the interface of that class or is it
>>allowed to use internals of the class ?
>>I did it in my adapter to directly access _order in OrderedContainer.
>>
>>I now have a working implementation which passes the tests and, of
>>cource, is doing what my application expects.
>>I have no test for the OrderedContainer adapter because I don'nt know
>>how to implement it.
>>
>>I did my changes on the release version of zope3.
>>Garret can you check it and if it seems good to you also commit it
>>into the trunk ?
>>I send my changes to you, just let me know your email.
>>
>>
>>Jürgen
>>
>>
>>_______________________________________________
>>Zope3-users mailing list
>>Zope3-users at zope.org
>>http://mail.zope.org/mailman/listinfo/zope3-users

-------------- next part --------------
<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:global_translation="http://namespaces.zope.org/gts"
    i18n_domain="zope"
    >

  <adapter
      factory="zope.app.copypastemove.ObjectMover"
      provides="zope.app.copypastemove.interfaces.IObjectMover"
      permission="zope.ManageContent"
      for="*"
      trusted="y"
      />

  <adapter
      factory="zope.app.copypastemove.ObjectRenamer"
      provides="zope.app.copypastemove.interfaces.IObjectRenamer"
      permission="zope.ManageContent"
      for="*"
      trusted="y"
      />

  <adapter
      factory="zope.app.copypastemove.ObjectCopier"
      provides="zope.app.copypastemove.interfaces.IObjectCopier"
      permission="zope.ManageContent"
      for="*"
      trusted="y"
      />

  <adapter
      factory="zope.app.copypastemove.PrincipalClipboard"
      provides="zope.app.copypastemove.interfaces.IPrincipalClipboard"
      for="zope.app.annotation.interfaces.IAnnotations"
      />

</configure>
-------------- next part --------------
##############################################################################
#
# 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: interfaces.py 27409 2004-09-02 07:05:38Z pruggera $
"""
__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 IObjectRenamer(Interface):
    '''Use `IObjectRenamer(container)` to rename within a container.'''

    def renameTo(oldName, newName):
        '''Rename oldName to newName.
        
        Returns the new name'''

    def renameable():
        '''Say if the container allows renaming.

        Returns ``True`` if container allows renaming, otherwise ``False``.
        '''

    def renameableTo(oldName, newName):
        '''Say whether the oldName can be renamed to newName.

        Returns ``True`` if it can be renamed. 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`, or ``None``
        if the target doesn't do names.
        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 IPrincipalClipboard(Interface):
    '''Interface for adapters that store/retrieve clipboard information
    for a principal.

    Clipboard information consists on tuples 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'''
-------------- next part --------------
##############################################################################
#
# 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.
#
##############################################################################
"""Test renaming of components

$Id: test_rename.py 27082 2004-08-12 20:03:58Z srichter $
"""
from unittest import TestCase, TestSuite, main, makeSuite

from zope.testing.doctestunit import DocTestSuite
from zope.app.tests.placelesssetup import setUp, tearDown
from zope.app.tests import ztapi

from zope.exceptions import NotFoundError, DuplicationError
from zope.app.traversing.api import traverse
from zope.app.site.tests.placefulsetup import PlacefulSetup
from zope.app.container.interfaces import IContainer
from zope.app.copypastemove.interfaces import IObjectRenamer
from zope.app.copypastemove import ObjectRenamer
from zope.app.copypastemove import rename

class File(object):
    pass

class RenameTest(PlacefulSetup, TestCase):

    def setUp(self):
        PlacefulSetup.setUp(self)
        PlacefulSetup.buildFolders(self)
        ztapi.provideAdapter(None, IObjectRenamer, ObjectRenamer)

    def test_simplerename(self):
        root = self.rootFolder
        folder1 = traverse(root, 'folder1')
        self.failIf('file1' in folder1)
        folder1['file1'] = File()
        rename(folder1, 'file1', 'my_file1')
        self.failIf('file1' in folder1)
        self.failUnless('my_file1' in folder1)

    def test_renamenonexisting(self):
        root = self.rootFolder
        folder1 = traverse(root, 'folder1')
        self.failIf('a_test_file' in folder1)
        self.assertRaises(NotFoundError, rename, folder1, 'file1', 'my_file1')

    def test_renamesamename(self):
        root = self.rootFolder
        folder1 = traverse(root, 'folder1')
        self.failIf('file1' in folder1)
        self.failIf('file2' in folder1)
        folder1['file1'] = File()
        folder1['file2'] = File()
        self.assertRaises(DuplicationError, rename, folder1, 'file1', 'file2')

def test_suite():
    suite = makeSuite(RenameTest)
    suite.addTest(
        DocTestSuite('zope.app.copypastemove',
                     setUp=setUp, tearDown=tearDown),
        )
    return suite

if __name__=='__main__':
    main(defaultTest='test_suite')


More information about the Zope3-users mailing list