home contents changes options help subscribe edit (external edit)

Acquisition and __parent__ pointers

Author: Philipp von Weitershausen
Status: IsProposal?
Version: 1.0
Last changed:2007-01-24

Abstract

This proposal aims at bringing Zope 2 a bit closer to Zope 3 by making the widely used Acquisition API aware of Zope 3's __parent__ pointers. This will alleviate the need of using Acquisition base classes in Zope 2 for every security-sensitive object, be it persistent or just a dynamically looked up component such as a view. The goal is to enable the use of Zope 3 components in Zope 2 straight away without creating subclasses that mix in Acquisition for security's sake.

Current situation

Object hierarchies in Zope 2

Zope 2's mechanism for expressing object hierarchies, in particular parent relationships, is Acquisition. It allows an object a that is acquired from an object b (e.g. through a simple getattr operation such as b.a) to gain an acquisition context in which one can tell "the parent" of object a (it is object b in this case) by using a simple API from the Acquisition package:

>>> from Acquisition import aq_parent
>>> aq_parent(b.a) == b
True

Security contexts in Zope 2

Acquisition also allows arbitrary attributes to be acquired from parent objects, either explicitly or implicitly. The canonical way of acquiring an attribute would be:

>>> b.name = "I'm b"
>>> a = b.a

>>> from Acquisition import aq_acquire
>>> aq_acquire(b, 'name')
"I'm b"

The Zope 2 security machinery uses this mechanism to acquire a security declaration closest to the currently accessed object.

Object hierarchies in Zope 3

In Zope 3, a much simpler system is used (because the ZODB nowadays supports cyclic references). Objects are assigned a __parent__ attribute when they are added to a container or when they are created dynamically as part of a traversal step (e.g. views after they've been looked up). Various other components make use of this API, such as Zope 3's default security policy, when investigating an objects hierarchical context.

Zope 3 views in Zope 2

Zope 3-style views in Zope 2 obviously need to have a proper parent context in order to function correctly with the Zope 2 security machinery. That means that currently all objects ever occurring in the traversal chain (and that includes views) need to inherit from at least Acquisition.Explicit and need to be acquisition-wrapped during traversal should they be created dynamically (which is the case with views).

This has led to a lot of code duplication in Five, the glue product between Zope 3 and Zope 2, because at least subclasses of essential core Zope 3 components had to be made to mix in Acquisition.Explicit.

Problem

Five copies a lot of core Zope 3 code, such as bases classes for browser views as well as the resource and viewlet implementations. The more core Zope 3 features are to be adopted, the more duplication has to occur. Likewise, code written for Zope 2 but using the Component Architecture will always be specific to Zope 2 as long as it has to use base classes from Five and not from Zope 3.

Proposal

  1. Objects inheriting from Acquisition.Explicit or Acquisition.Implicit that have an acquisition wrapper will gain a __parent__ attribute. It will be synonymous with the currently already available aq_parent attribute. The canonical way for Zope3-style code for getting an objects parent will therefore be:

    >>> obj.__parent__
    
  2. The functional Acquisition API (aq_parent, aq_acquire, etc.) is extended to deal with objects that don't subclass Implicit or Explicit but have a __parent__ attribute. An object with a __parent__ attribute will be treated just like an object inheriting from Explicit in terms of acquisition, e.g.:

    >>> b.name = "I'm b"
    >>> a.__parent__ = b
    >>> from Acquisition import aq_acquire
    >>> aq_acquire(a, 'name')
    

    This will be, as it already should be, the canonical way of acquiring things.

With this in place, Zope 3-style components (or any other Zope 2 object for that matter) won't have to subclass from any of the Acquisition base classes anymore in order to play nice with the security machinery. Subsequently, much of Five's code duplication will become unnecessary.

Risks

None envisioned

Implementation status

In terms of features, a complete implementation of this proposal has been checked into the philikon-aq-and-__parent__ branch of Zope. All tests of the Acquisition package pass (incl. the added ones that test the new behaviour). However, running tests for all of Zope dumps core. There's also a test failure in AccessControl? now that shouldn't occur.

Help with the implementation (e.g. a code review of the check ins, revisions 71219 thru 71229) is highly appreciated. Whoever will help fix the problem that I as an unexperienced C programmer can't seem to debug, not to mention fix, will get a signed copy of my book :). (This offer is limited to the one person making the checkin)



subject:
  ( 23 subscribers )