[Zope-dev] Zope Tests: 41 OK, 13 Failed

Marius Gedminas marius at gedmin.as
Sun Dec 19 12:51:08 EST 2010


On Sun, Dec 19, 2010 at 06:45:11PM +0200, Marius Gedminas wrote:
> > Subject: FAILED : winbot / z3c.contents_py_265_32
> > From: buildbot at winbot.zope.org
> > Date: Sat Dec 18 23:06:16 EST 2010
> > URL: http://mail.zope.org/pipermail/zope-tests/2010-December/027073.html
> 
> Interesting.
> 
> c:\buildslave\z3c.contents\build\src\z3c\contents\README.txt, while testing
> copy & paste near line 613, ends up deep in zope.copy.clone() which barfs
> with
> 
>     TypeError: non-picklable object

tl;dr: zope.copy is badly broken.

The test here creates a simple Content object:

    class Content(object):
        """Sample content which is pickable for copy test."""

        zope.interface.implements(IContent)

        def __init__(self, title, number):
            self.title = title
            self.number = number

        def __repr__(self):
            return u'<%s %s %s>' % (self.__class__.__name__, self.title,
                self.number)

It is not persistent, so it gets wrapped in a ContainedProxy.

And then z3c.contents does

    copier = IObjectCopier(obj)
    copier.copyTo(self.context)

and zope.copypastemove.ObjectCopier.copyTo() does

    new = copy(obj)

and zope.copy.copy() does

    res = clone(obj)
    res.__parent__ = None # wrapped in an if and a try/except.

in that order, and zope.copy.clone() does

    tmp = tempfile.TemporaryFile()
    persistent = CopyPersistent(obj)
    pickler = cPickle.Pickler(tmp, 2)
    pickler.persistent_id = persistent.id
    pickler.dump(obj)

which tries to pickle an unpickleable ViewPageTemplateFile.  Why?
Because of it's reachable through this chain of references:
http://mg.pov.lt/contained-proxy-pickles-too-much.png

Yes, copying any object with zope.copypastemove makes a copy of your
entire ZODB contents, and then discards it a bit later, by dropping the
__parent__ *after* copying it.

(I have a feeling of deja-vu here, but Google doesn't support me.)

I suppose setting __parent__ to None *before* copying is out of the
question.  How about making pickler.persistent_id check the object against
a blacklist -- containing the __parent__ we don't want to copy -- before
passing it on to persistent.id?

I'll go file a bug at https://bugs.launchpad.net/zope.copy

Marius Gedminas
-- 
http://pov.lt/ -- Zope 3/BlueBream consulting and development
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
Url : http://mail.zope.org/pipermail/zope-dev/attachments/20101219/b1e61123/attachment.bin 


More information about the Zope-Dev mailing list