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

Attachment: signature.asc
Description: Digital signature

_______________________________________________
Zope-Dev maillist  -  Zope-Dev@zope.org
https://mail.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 https://mail.zope.org/mailman/listinfo/zope-announce
 https://mail.zope.org/mailman/listinfo/zope )

Reply via email to