Diving into Plone’s guts

by John Samuel Anderson last modified Jan 10, 2010 12:46 AM
Locating the affected code.

Editing the Source Code

The file we need to examine is this:

/var/Plone/eggs/ZODB3-3.8.1b7-py2.4-linux-x86_64.egg/ZEO/zrpc/connection.py

In a text editor (vim, in my case), line 699 is inside this block of code:

    def call(self, method, *args):
        if self.closed:
            raise DisconnectedError()
        msgid = self.send_call(method, args, 0)
        r_flags, r_args = self.wait(msgid)
        if (isinstance(r_args, tuple) and len(r_args) > 1
            and type(r_args[0]) == exception_type_type
            and issubclass(r_args[0], Exception)):
            inst = r_args[1]
            raise inst # error raised by server
        else:
            return r_args

What we want to do is find out what's going on. To do so, let's put a pdb.set_trace() call in.

Where should we put the set_trace?

We could put it right at the top, like this, but then we'd have to deal with cases where it's working correctly:

    def call(self, method, *args):
        import pdb; pdb.set_trace()
        if self.closed:
            raise DisconnectedError()
        msgid = self.send_call(method, args, 0)
        r_flags, r_args = self.wait(msgid)

A better place would be right before the "raise" statement, like this:

        if (isinstance(r_args, tuple) and len(r_args) > 1
            and type(r_args[0]) == exception_type_type
            and issubclass(r_args[0], Exception)):
            inst = r_args[1]
            import pdb; pdb.set_trace();
            raise inst # error raised by server
        else:
            return r_args

Save the file. Now, we need to restart the Zope instance in the foreground and re-issue the request via the ZMI. (And wait.)

Bonus: How to tell that your changes were included

When it restarts, Zope will recompile the connection.py file.  If you're really curious, or want to verify that your changes were compiled, you can list that file's parent directory on the file system.  In linux, "ls -lasF" is very nice for that.  Look for a connection.pyc file with a file-date that is newer than the connection.py file itself.

Why bother? Sometimes there are multiple versions of the file on the filesystem.  For example, Plone downloads the egg for plone.app.blob automatically, but your buildout also downloads your own version of plone.app.blob as an svnproduct.  It's an odd situation, I know, but be aware that odd situations sometimes happen around Plone.  (That's why it's so flexible.)