• Acquisition Report

  last modified March 24, 2007 by philikon

Philipp had announced that he wanted to work on his Acquisition + __parent__ proposal for Zope 2 during the Sprint, but needed some debugging assistance from a C savvy developer to find an issue with the branch he had prepared. One of the sprinters took up the challenge and spent many hours debugging the problem. On Day 3 of the sprint, he and Philipp tracked the issue down to an infinite recursion:

Prerequisites

  • Suppose we have a content object that inherits from Acquisition.Implicit and a view which operates on that object (as a Five view it inherits from Acquisition.Explicit).
  • The view itself is not wrapped. This doesn't happen often in Zope 2 because views are typically wrapped during traversal. One case where views are unwrapped is when they're instantiated and their __init__ is executed.
  • zope.publisher.browser.BrowserView defines a __parent__ property that falls back to "self.context" if not set explicitly.

Recursion

  1. Suppose the unwrapped view (e.g. in its __init__) wants to access an attribute on the content object (self.context) which does not (yet) exist. When accessing self.context, the content object's acquisition chain contains itself and the view (because we got to it using attribute access).
  2. The content object doesn't have the attribute, so implicit acquisition kicks in and goes up the acquisition chain. The next (and last item) is the view. It doesn't have the attribute either, so acquisition continues: the view is unwrapped but it has a __parent__ attribute which points to self.context. Go to #1.

This issue is pathological though also somewhat common as Implicit is used often as a base class for content objects in Zope 2.

Solution

We came up with several solutions (which may have to be applied all at the same time). It isn't sure if any of them solve the probelm adequately at this point, careful testing will have to be conducted:

  • Make sure that self.context doesn't yield context in a different acquisition chain (by defining context as a dynamic property)
  • Add another check to the acquisition code that won't traverse __parent__ for Implicit/Explicit subclasses