Shane's Aquisition Understander
Here's an external method to show you how acquisition works by showing the relationship between the acquisition wrappers used in rendering the current object.
The method, instead of showing the acquisition algebra, shows the actual graph of acquisition wrappers. It's ordered in such a way that you can search it from top to bottom to figure out exactly the behavior of Acquisition.c.
A vertical line refers to aq_parent, which is a "context" link. A diagonal line refers to aq_self, which is a "containment" link. Containment never changes; it refers to the physical location of an object. Context, on the other hand, can be modified easily just by changing the URL.
Some objects are in parentheses because they are not actually searched. But you'll notice that objects in parentheses have both an aq_self and an aq_parent which refer to the same object. Shane supposed this method could be cleaned up to eliminate the redundancy, but his goal was to see the actual structure of the wrappers.
Install the external method as "showaq" at the base of your Zope installation. Then try different acquisition paths:
http://localhost:8080/QuickStart/showaq http://localhost:8080/QuickStart/Outline/QuickStart/showaq http://localhost:9080/QuickStart/Outline/QuickStart/Control_Panel/showaq
Here's the code for the method:
def showaq(self, indent=''): rval = "" obj = self base = getattr(obj, 'aq_base', obj) try: id = base.id except: id = str(base) try: id = id() except: pass if hasattr(obj, 'aq_self'): if hasattr(obj.aq_self, 'aq_self'): rval = rval + indent + "(" + id + ")\n" rval = rval + indent + "| \\\n" rval = rval + showaq(obj.aq_self, '| ' + indent) rval = rval + indent + "|\n" if hasattr(obj, 'aq_parent'): rval = rval + indent + id + "\n" rval = rval + indent + "|\n" rval = rval + showaq(obj.aq_parent, indent) else: rval = rval + indent + id + "\n" return rval