[Checkins] SVN: zope2book/trunk/ Restify Acquisition chapter.
Tres Seaver
tseaver at palladion.com
Tue Feb 10 14:05:35 EST 2009
Log message for revision 96408:
Restify Acquisition chapter.
Changed:
D zope2book/trunk/Acquisition.stx
A zope2book/trunk/source/Acquisition.rst
U zope2book/trunk/source/index.rst
-=-
Deleted: zope2book/trunk/Acquisition.stx
===================================================================
--- zope2book/trunk/Acquisition.stx 2009-02-10 18:53:34 UTC (rev 96407)
+++ zope2book/trunk/Acquisition.stx 2009-02-10 19:05:30 UTC (rev 96408)
@@ -1,361 +0,0 @@
-Acquisition
-
- Acquisition is the technology that allows dynamic behavior to be
- shared between Zope objects via *containment*.
-
- Acquisition's flavor permeates Zope and can be used almost
- everywhere within Zope: in DTML, in Zope Page Templates, in Script
- (Python) objects, and even in Zope URLs. Because of its ubiquity in
- Zope, a basic understanding of acquisition is important.
-
- Acquisition vs. Inheritance
-
- The chapter entitled "Object Orientation":ObjectOrientation.stx
- describes a concept called *inheritance*. Using inheritance, an
- object can *inherit* some of the behaviors of a specific class,
- *overriding* or adding other behaviors as necessary. Behaviors of
- a class are nearly always defined by its *methods*, although
- attributes can be inherited as well.
-
- In a typical object-oriented language, there are rules that define the way
- a *subclass* inherits behavior from its *superclasses*. For
- example, in Python (a *multiple-inheritance* language), a class
- may have more than one superclass, and rules are used to determine
- which of a class' superclasses is used to define behavior in any
- given circumstance.
-
- We'll define a few Python classes here to demonstrate. You don't
- really need to know Python inside and out to understand these
- examples. Just know that a 'class' statement defines a class, and
- a 'def' statement inside of a class statement defines a method.
- A class statement followed by one or more words inside (parentheses)
- causes that class to *inherit* behavior from the classes named in
- the parentheses (you can play along at home if you like, using the
- Python interpreter).::
-
- >>> class SuperA:
- ... def amethod(self):
- ... print "I am the 'amethod' method of the SuperA class"
- ... def anothermethod(self):
- ... print "I am the 'anothermethod' method of the SuperA class"
- ...
- >>> class SuperB:
- ... def amethod(self):
- ... print "I am the 'amethod' method of the SuperB class"
- ... def anothermethod(self):
- ... print "I am the 'anothermethod' method of the SuperB class"
- ... def athirdmethod(self):
- ... print "I am the 'athirdmethod' method of the SuperB class"
- ...
- >>> class Sub(SuperA, SuperB):
- ... def amethod(self):
- ... print "I am the 'amethod' method of the Sub class"
- ...
-
- If we make an *instance* of the "Sub" class, and attempt to *call*
- one of its methods, there are rules in place to determine whether
- the behavior of the method will be defined by the Sub class
- itself, its SuperA superclass, or its SuperB superclass. The
- rules are fairly simple: if the Sub class has itself defined the
- named method, that method definition will be used. Otherwise, the
- *inheritance hierarchy* will be searched for a method definition.
-
- The *inheritance hierarchy* is defined by the class' superclass
- definitions. The case of the Sub class above has a simple
- inheritance hierarchy: it inherits first from the SuperA
- superclass, then it inherits from the SuperB superclass. This
- means that if you call a method on an instance of the Sub class,
- and that method is not defined as part of the Sub class'
- definition, it will first search for the method in the SuperA
- class. If it doesn't find it there, it will search in the
- SuperB class. Python performs this search of the base classes
- using an order derived from the order of declaration. Note that for
- complex cases (e.g., where the same method is defined in several
- ancestors of base classes), the lookup order is too complicated to
- explain within the scope of this book. Please see the online
- Python documentation for the "method resolution order",
- http://www.python.org/download/releases/2.3/mro/
-
- Here is an example of calling methods on an instance of the
- above-defined Sub class::
-
- >>> instance = Sub()
- >>> instance.amethod()
- I am the 'amethod' method of the Sub class
- >>> instance.anothermethod()
- I am the 'anothermethod' method of the SuperA class
- >>> instance.athirdmethod()
- I am the 'athirdmethod' method of the SuperB class
-
- Note that when we called the 'anothermethod' method on the Sub
- instance, we got the return value of SuperA's method definition
- for that method, even though both SuperA and SuperB defined that
- method. This is because the inheritance hierarchy specifies that
- the first superclass (SuperA) is searched first.
-
- The point of this example is that instances of objects use their
- *inheritance hierarchy* to determine their behavior. In non-Zope
- applications, this is the only way that object instances know
- about their set of behaviors. However, in Zope, objects make use
- of another facility to search for their behaviors: *acquisition*.
-
- Acquisition Is about Containment
-
- The concept behind acquisition is
- simple:
-
- - Objects are situated inside other objects, and these objects act as
- their "containers". For example, the container of a DTML Method
- named "amethod" inside the DTML_Example folder is the
- DTML_Example folder.
-
- - Objects may acquire behavior from their containers.
-
- Inheritance stipulates that an object can learn about its behavior
- from its superclasses via an *inheritance hierarchy*.
- *Acquisition*, on the other hand, stipulates that an object can
- additionally learn about its behavior through its *containment
- hierarchy*. In Zope, an object's inheritance hierarchy is always
- searched for behavior before its acquisition hierarchy. If the
- method or attribute is not found in the object's inheritance
- hierarchy, then the acquisition hierarchy is searched.
-
- Say What?
-
- Let's toss aside the formal explanations. Acquisition can be
- best explained with a simple example.
-
- Place a DTML Method named 'acquisition_test' in your Zope root
- folder. Give it the following body::
-
- <html>
- <body>
- <p>
- I am being called from within the <dtml-var title> Folder!
- </p>
- </body>
- </html>
-
- Save it, and then use the DTML Method "View" tab to see the result
- of the DTML method in your Workspace frame. You will see
- something not unlike the following::
-
- I am being called from within the Zope Folder!
-
- The 'title' of the Zope root folder is 'Zope', so this makes
- sense. Now create a Folder inside your Zope root folder
- named 'AcquisitionTestFolder' and a title of
- "TheAcquisitionTest". We're going to invoke the
- 'acquisition_test' method *in the context of* the
- AcquisitionTestFolder folder. To do this, assuming your
- Zope is running on your local machine on port 8080, visit
- the URL
- 'http://localhost:8080/AcquisitionTestFolder/acquisition_test'.
- You will see something not unlike the following::
-
- I am being called from within the TheAcquisitionTest Folder!
-
- Note that even though an object named 'acquisition_test' does not
- "live" inside the AcquisitionTestFolder folder, Zope found the
- method and displayed a result anyway! Not only did Zope display a
- result, instead of inserting the 'title' of the Zope root folder, it
- inserted the 'title' of the AcquisitionTestFolder folder!
-
- This is an example of acquisition in action. The concept is simple:
- if a named object is not found as an attribute of the object you're
- searching, its containers are searched until the object is found.
- In this way, acquisition can *add behavior* to objects. In this
- case, we added a behavior to the AcqusitionTestFolder folder that
- it didn't have before (by way of giving it an 'acquisition_test'
- method).
-
- Providing Services
-
- It can be said that acquisition allows objects to acquire
- *services* by way of containment. For example, our
- AcquisitionTestFolder folder acquired the services of the
- 'acquisition_test' method.
-
- Not only do objects *acquire* services, but they also *provide* them. For
- example, adding a Mail Host object to a Folder named 'AFolder'
- provides other objects in that folder with the ability to send
- mail. But it also provides objects contained in *subfolders* of
- that folder with the capability to send mail. If you create
- subfolders of 'AFolder' named 'AnotherFolder' and 'AThirdFolder',
- you can be assured that objects placed in *these* folders will
- also be able to send mail in exactly the same way as objects
- placed in 'AFolder'.
-
- Acquisition "goes both ways": when you create an object in Zope,
- it has the capability to automatically acquire services.
- Additionally, it automatically provides services that other
- objects can acquire. This makes reuse of services very easy, since
- you don't have to do anything special in order to make services available
- to other objects.
-
- Getting Deeper with Multiple Levels
-
- If you place a method in the root folder, and create a subfolder
- in the root folder, you can acquire the method's behaviors. So
- what happens if things get more complex? Perhaps you have a
- method that needs to be acquired from within a couple of
- folders. Is it acquired from its parent, or its parent's parent,
- or what?
-
- The answer is that acquisition works on the entire object
- hierarchy. If, for example, you have a DTML Method, "HappySong",
- in the root folder, and also in the root folder you have three
- nested Folders named "Users", "Barney" and "Songs",
- you may call this URL::
-
- /Users/Barney/Songs/HappySong
-
- The HappySong method is found in the root folder, unless one of the
- other folders "Users", "Barney" or "Songs" happens to also have a
- method named "HappySong", in which case *that* method is used instead.
- The HappySong method is searched for first directly in the "Songs"
- folder. If it is not found, the acquisition hierarchy is searched
- starting at the first container in the hierarchy: "Barney". If it
- is not found in "Barney", the "Users" folder is searched. If it
- is not found in the "Users" folder, the root folder is searched.
- This search is called *searching the acquisition path* or
- alternately *searching the containment hierarchy*.
-
- Acquisition is not limited to searching a containment hierarchy: it
- can also search a *context hierarchy*. Acquisition by context is
- terribly difficult to explain, and you should avoid it if at all
- possible. However, if you want more information about acquiring
- via a context, and you are prepared to allow your brain to explode, please
- see the presentation named "Acquisition Algebra":http://zope.org/Members/jim/Info/IPC8/AcquisitionAlgebra/index.html.
-
- In the example above, for instance, in order to find and publish
- the "HappySong" template at the end of the URL, acquisition searches
- the *containment hierarchy* of the "Songs" folder first. Because
- "Songs" is contained within "Barney", and "Barney" within "Users",
- the *containment hierarchy* for "Songs" consists of each folder "up"
- from "Users" to the root.
-
- Once the "HappySongs" template is found, there are two hierarchies of
- interest:
-
- - Because "HappySongs" is located directly within the root, its
- *containment hierarchy* consists of only itself and the root.
-
- - Because "HappySongs" was found by traversing first through the
- "Users", "Barney", and "Songs" folders, its *context hierarchy*
- includes those objects.
-
- Acquisition searches the *context hierarchy* only after failing
- to find the named object in the *containment hierarchy*.
-
- As with understanding Python's concept of multiple inheritance, explaining
- the exact strategy used to order that search is not within the scope of this
- book. Please see the following resources for further enlightenment:
-
- - Jim Fulton's "Acquisition Algebra presentation",
- http://zope.org/Members/jim/Info/IPC8/AcquisitionAlgebra/index.html
- is the authoritative theoretical specification for acquisition.
-
- - Shane Hathaway's "Acquisition Explorer (XXX xp?)",
- http://hathaway.freezope.org/XXX/path/to/aq_explorer
- allows you to visualize both the containment and context
- hierarchies.
-
- The example below uses the Zope debugger to examine the two
- acquisition hierarchies.
-
-
- Example: The Nitty-Gritty Details of the HappySong Acquisition
-
- Run 'bin/zopectl debug' in your Zope's instance home (don't call
- 'get_transaction().commit()' unless you want to make the example
- a permanent part of your Zope!)::
-
- $ bin/zopectl debug
- Starting debugger (the name "app" is bound to the top-level Zope object)
- >>> app.manage_addFolder('Users')
- >>> users = app.Users
- >>> users.manage_addFolder('Barney')
- >>> barney = users.Barney
- >>> barney.manage_addFolder('Songs')
- >>> songs = barney.Songs
- >>> songs.aq_chain # show the whole chain
- [<Folder instance at f651b290>, <Folder instance at f651b260>, <Folder instance at f651b230>, <Application instance at f65b0290>]
- >>> songs.aq_inner.aq_chain # show only containment; here its the same
- [<Folder instance at f651b290>, <Folder instance at f651b260>, <Folder instance at f651b230>, <Application instance at f65b0290>]
-
- In the example so far, we can see the *containment hierarchy* for
- the "Songs" folder; because the only objects searched to find
- "Songs" were also in its *containment hierarchy*, the *context
- hierarchy* and *containment hierarchy* are identical.
-
- Now, let's create the "HappySongs" template and examine its
- *containment hierarchy*. In this case, the two hierarchies are again
- identical::
-
- >>> app.manage_addDTMLMethod('HappySong', file="""\
- ... <dtml-if favorite_color>
- ... My favorite color is &dtml-favorite_color;.
- ... <dtml-else>
- ... I don't have a favorite color.
- ... </dtml-if>
- ... """)
- ''
- >>> happy = app.HappySong
- >>> happy.aq_chain
- [<DTMLMethod instance at f649d050>, <Application instance at f65b0290>]
- >>> happy.aq_inner.aq_chain
- [<DTMLMethod instance at f649d050>, <Application instance at f65b0290>]
-
- Now we will emulate the method the publisher uses to publish the
- URL, '/Users/Barney/Songs/HappySong', fetching it in the context of
- the "Songs" folder::
-
- >>> happy2 = app.unrestrictedTraverse('/Users/Barney/Songs/HappySong')
- >>> happy2.aq_chain
- [<extension class OFS.DTMLMethod.DTMLMethod at f6b0d980>, <extension class OFS.Application.Application at f6a234d0>]
- >>> happy2.aq_inner.aq_chain
- [<DTMLMethod instance at f651b320>, <Application instance at f65b0290>]
-
- Note that the *containment* hierarchy (fetched via
- 'happy2.aq_inner.aq_chain' ) is the same as in the previous example,
- except that the *context hierarchy* includes all of the folders through
- which we have traversed.
-
- Now let's experiment with finding things via acquisition using both
- hierarchies. First, we show the case where the template cannot
- acquire 'favorite_color'::
-
- >>> happy2(songs, {}, None)
- " I don't have a favorite color.\n"
-
- Then, we set the 'favorite_color' attribute on one of the items in
- the *context hierarchy*, and the template is able to use it::
-
- >>> barney.favorite_color = 'purple'
- >>> happy2(songs, {}, None)
- ' My favorite color is purple.\n'
-
- Summary
-
- Acquisition allows behavior to be distributed hierarchically throughout the
- system. When you add a new object to Zope, you don't need to
- specify all of its behavior, only the part of its behavior that is
- unique to that object. For the rest of its behavior, it relies on other
- objects. This means that you can change an object's behavior by
- changing where it is located in the object hierarchy. This is a
- very powerful function that gives your Zope applications
- flexibility.
-
- Acquisition is useful for providing objects with behavior that
- doesn't need to be specified by their own methods or methods found
- in their inheritance hierarchies. Acquisition is particularly
- useful for sharing information (such as headers and footers)
- between objects in different folders as well. You will see how
- you can make use of acquisition within different Zope technologies
- in upcoming chapters.
-
- A more exhaustive technical explanation of the underpinnings of
- Zope's acquisition technology is available in the "Zope
- Developer's
- Guide":http://www.zope.org/Documentation/ZDG/Acquisition.stx.
Copied: zope2book/trunk/source/Acquisition.rst (from rev 96406, zope2book/trunk/Acquisition.stx)
===================================================================
--- zope2book/trunk/source/Acquisition.rst (rev 0)
+++ zope2book/trunk/source/Acquisition.rst 2009-02-10 19:05:30 UTC (rev 96408)
@@ -0,0 +1,368 @@
+Acquisition
+###########
+
+Acquisition is the technology that allows dynamic behavior to be
+shared between Zope objects via *containment*.
+
+Acquisition's flavor permeates Zope and can be used almost
+everywhere within Zope: in DTML, in Zope Page Templates, in Script
+(Python) objects, and even in Zope URLs. Because of its ubiquity in
+Zope, a basic understanding of acquisition is important.
+
+Acquisition vs. Inheritance
+===========================
+
+The chapter entitled `Object Orientation <ObjectOrientation.html>`_
+describes a concept called *inheritance*. Using inheritance, an
+object can *inherit* some of the behaviors of a specific class,
+*overriding* or adding other behaviors as necessary. Behaviors of
+a class are nearly always defined by its *methods*, although
+attributes can be inherited as well.
+
+In a typical object-oriented language, there are rules that define the way
+a *subclass* inherits behavior from its *superclasses*. For
+example, in Python (a *multiple-inheritance* language), a class
+may have more than one superclass, and rules are used to determine
+which of a class' superclasses is used to define behavior in any
+given circumstance.
+
+We'll define a few Python classes here to demonstrate. You don't
+really need to know Python inside and out to understand these
+examples. Just know that a 'class' statement defines a class, and
+a 'def' statement inside of a class statement defines a method.
+A class statement followed by one or more words inside (parentheses)
+causes that class to *inherit* behavior from the classes named in
+the parentheses (you can play along at home if you like, using the
+Python interpreter).::
+
+ >>> class SuperA:
+ ... def amethod(self):
+ ... print "I am the 'amethod' method of the SuperA class"
+ ... def anothermethod(self):
+ ... print "I am the 'anothermethod' method of the SuperA class"
+ ...
+ >>> class SuperB:
+ ... def amethod(self):
+ ... print "I am the 'amethod' method of the SuperB class"
+ ... def anothermethod(self):
+ ... print "I am the 'anothermethod' method of the SuperB class"
+ ... def athirdmethod(self):
+ ... print "I am the 'athirdmethod' method of the SuperB class"
+ ...
+ >>> class Sub(SuperA, SuperB):
+ ... def amethod(self):
+ ... print "I am the 'amethod' method of the Sub class"
+ ...
+
+If we make an *instance* of the "Sub" class, and attempt to *call*
+one of its methods, there are rules in place to determine whether
+the behavior of the method will be defined by the Sub class
+itself, its SuperA superclass, or its SuperB superclass. The
+rules are fairly simple: if the Sub class has itself defined the
+named method, that method definition will be used. Otherwise, the
+*inheritance hierarchy* will be searched for a method definition.
+
+The *inheritance hierarchy* is defined by the class' superclass
+definitions. The case of the Sub class above has a simple
+inheritance hierarchy: it inherits first from the SuperA
+superclass, then it inherits from the SuperB superclass. This
+means that if you call a method on an instance of the Sub class,
+and that method is not defined as part of the Sub class'
+definition, it will first search for the method in the SuperA
+class. If it doesn't find it there, it will search in the
+SuperB class. Python performs this search of the base classes
+using an order derived from the order of declaration. Note that for
+complex cases (e.g., where the same method is defined in several
+ancestors of base classes), the lookup order is too complicated to
+explain within the scope of this book. Please see the online
+Python documentation for the "method resolution order",
+http://www.python.org/download/releases/2.3/mro/
+
+Here is an example of calling methods on an instance of the
+above-defined Sub class::
+
+ >>> instance = Sub()
+ >>> instance.amethod()
+ I am the 'amethod' method of the Sub class
+ >>> instance.anothermethod()
+ I am the 'anothermethod' method of the SuperA class
+ >>> instance.athirdmethod()
+ I am the 'athirdmethod' method of the SuperB class
+
+Note that when we called the 'anothermethod' method on the Sub
+instance, we got the return value of SuperA's method definition
+for that method, even though both SuperA and SuperB defined that
+method. This is because the inheritance hierarchy specifies that
+the first superclass (SuperA) is searched first.
+
+The point of this example is that instances of objects use their
+*inheritance hierarchy* to determine their behavior. In non-Zope
+applications, this is the only way that object instances know
+about their set of behaviors. However, in Zope, objects make use
+of another facility to search for their behaviors: *acquisition*.
+
+Acquisition Is about Containment
+================================
+
+The concept behind acquisition is simple:
+
+- Objects are situated inside other objects, and these objects act as
+ their "containers". For example, the container of a DTML Method
+ named "amethod" inside the DTML_Example folder is the
+ DTML_Example folder.
+
+- Objects may acquire behavior from their containers.
+
+Inheritance stipulates that an object can learn about its behavior
+from its superclasses via an *inheritance hierarchy*.
+*Acquisition*, on the other hand, stipulates that an object can
+additionally learn about its behavior through its *containment
+hierarchy*. In Zope, an object's inheritance hierarchy is always
+searched for behavior before its acquisition hierarchy. If the
+method or attribute is not found in the object's inheritance
+hierarchy, then the acquisition hierarchy is searched.
+
+Say What?
+=========
+
+Let's toss aside the formal explanations. Acquisition can be
+best explained with a simple example.
+
+Place a DTML Method named 'acquisition_test' in your Zope root
+folder. Give it the following body::
+
+ <html>
+ <body>
+ <p>
+ I am being called from within the <dtml-var title> Folder!
+ </p>
+ </body>
+ </html>
+
+Save it, and then use the DTML Method "View" tab to see the result
+of the DTML method in your Workspace frame. You will see
+something not unlike the following::
+
+ I am being called from within the Zope Folder!
+
+The 'title' of the Zope root folder is 'Zope', so this makes
+sense. Now create a Folder inside your Zope root folder
+named 'AcquisitionTestFolder' and a title of
+"TheAcquisitionTest". We're going to invoke the
+'acquisition_test' method *in the context of* the
+AcquisitionTestFolder folder. To do this, assuming your
+Zope is running on your local machine on port 8080, visit
+the URL
+'http://localhost:8080/AcquisitionTestFolder/acquisition_test'.
+You will see something not unlike the following::
+
+ I am being called from within the TheAcquisitionTest Folder!
+
+Note that even though an object named 'acquisition_test' does not
+"live" inside the AcquisitionTestFolder folder, Zope found the
+method and displayed a result anyway! Not only did Zope display a
+result, instead of inserting the 'title' of the Zope root folder, it
+inserted the 'title' of the AcquisitionTestFolder folder!
+
+This is an example of acquisition in action. The concept is simple:
+if a named object is not found as an attribute of the object you're
+searching, its containers are searched until the object is found.
+In this way, acquisition can *add behavior* to objects. In this
+case, we added a behavior to the AcqusitionTestFolder folder that
+it didn't have before (by way of giving it an 'acquisition_test'
+method).
+
+Providing Services
+==================
+
+It can be said that acquisition allows objects to acquire
+*services* by way of containment. For example, our
+AcquisitionTestFolder folder acquired the services of the
+'acquisition_test' method.
+
+Not only do objects *acquire* services, but they also *provide* them. For
+example, adding a Mail Host object to a Folder named 'AFolder'
+provides other objects in that folder with the ability to send
+mail. But it also provides objects contained in *subfolders* of
+that folder with the capability to send mail. If you create
+subfolders of 'AFolder' named 'AnotherFolder' and 'AThirdFolder',
+you can be assured that objects placed in *these* folders will
+also be able to send mail in exactly the same way as objects
+placed in 'AFolder'.
+
+Acquisition "goes both ways": when you create an object in Zope,
+it has the capability to automatically acquire services.
+Additionally, it automatically provides services that other
+objects can acquire. This makes reuse of services very easy, since
+you don't have to do anything special in order to make services available
+to other objects.
+
+Getting Deeper with Multiple Levels
+===================================
+
+If you place a method in the root folder, and create a subfolder
+in the root folder, you can acquire the method's behaviors. So
+what happens if things get more complex? Perhaps you have a
+method that needs to be acquired from within a couple of
+folders. Is it acquired from its parent, or its parent's parent,
+or what?
+
+The answer is that acquisition works on the entire object
+hierarchy. If, for example, you have a DTML Method, "HappySong",
+in the root folder, and also in the root folder you have three
+nested Folders named "Users", "Barney" and "Songs",
+you may call this URL::
+
+ /Users/Barney/Songs/HappySong
+
+The HappySong method is found in the root folder, unless one of the
+other folders "Users", "Barney" or "Songs" happens to also have a
+method named "HappySong", in which case *that* method is used instead.
+The HappySong method is searched for first directly in the "Songs"
+folder. If it is not found, the acquisition hierarchy is searched
+starting at the first container in the hierarchy: "Barney". If it
+is not found in "Barney", the "Users" folder is searched. If it
+is not found in the "Users" folder, the root folder is searched.
+This search is called *searching the acquisition path* or
+alternately *searching the containment hierarchy*.
+
+Acquisition is not limited to searching a containment hierarchy: it
+can also search a *context hierarchy*. Acquisition by context is
+terribly difficult to explain, and you should avoid it if at all
+possible. However, if you want more information about acquiring
+via a context, and you are prepared to allow your brain to explode, please
+see the presentation named `Acquisition Algebra
+<http://zope.org/Members/jim/Info/IPC8/AcquisitionAlgebra/index.html>`_.
+
+In the example above, for instance, in order to find and publish
+the "HappySong" template at the end of the URL, acquisition searches
+the *containment hierarchy* of the "Songs" folder first. Because
+"Songs" is contained within "Barney", and "Barney" within "Users",
+the *containment hierarchy* for "Songs" consists of each folder "up"
+from "Users" to the root.
+
+Once the "HappySongs" template is found, there are two hierarchies of
+interest:
+
+- Because "HappySongs" is located directly within the root, its
+ *containment hierarchy* consists of only itself and the root.
+
+- Because "HappySongs" was found by traversing first through the
+ "Users", "Barney", and "Songs" folders, its *context hierarchy*
+ includes those objects.
+
+Acquisition searches the *context hierarchy* only after failing
+to find the named object in the *containment hierarchy*.
+
+As with understanding Python's concept of multiple inheritance, explaining
+the exact strategy used to order that search is not within the scope of this
+book. Please see the following resources for further enlightenment:
+
+- Jim Fulton's "Acquisition Algebra presentation",
+ http://zope.org/Members/jim/Info/IPC8/AcquisitionAlgebra/index.html
+ is the authoritative theoretical specification for acquisition.
+
+- Shane Hathaway's "Acquisition Explorer (XXX xp?)",
+ http://hathaway.freezope.org/XXX/path/to/aq_explorer
+ allows you to visualize both the containment and context
+ hierarchies.
+
+The example below uses the Zope debugger to examine the two
+acquisition hierarchies.
+
+
+Example: The Nitty-Gritty Details of the HappySong Acquisition
+===============================================================
+
+Run 'bin/zopectl debug' in your Zope's instance home (don't call
+'get_transaction().commit()' unless you want to make the example
+a permanent part of your Zope!)::
+
+ $ bin/zopectl debug
+ Starting debugger (the name "app" is bound to the top-level Zope object)
+ >>> app.manage_addFolder('Users')
+ >>> users = app.Users
+ >>> users.manage_addFolder('Barney')
+ >>> barney = users.Barney
+ >>> barney.manage_addFolder('Songs')
+ >>> songs = barney.Songs
+ >>> songs.aq_chain # show the whole chain
+ [<Folder instance at f651b290>, <Folder instance at f651b260>, <Folder instance at f651b230>, <Application instance at f65b0290>]
+ >>> songs.aq_inner.aq_chain # show only containment; here its the same
+ [<Folder instance at f651b290>, <Folder instance at f651b260>, <Folder instance at f651b230>, <Application instance at f65b0290>]
+
+In the example so far, we can see the *containment hierarchy* for
+the "Songs" folder; because the only objects searched to find
+"Songs" were also in its *containment hierarchy*, the *context
+hierarchy* and *containment hierarchy* are identical.
+
+Now, let's create the "HappySongs" template and examine its
+*containment hierarchy*. In this case, the two hierarchies are again
+identical::
+
+ >>> app.manage_addDTMLMethod('HappySong', file="""\
+ ... <dtml-if favorite_color>
+ ... My favorite color is &dtml-favorite_color;.
+ ... <dtml-else>
+ ... I don't have a favorite color.
+ ... </dtml-if>
+ ... """)
+ ''
+ >>> happy = app.HappySong
+ >>> happy.aq_chain
+ [<DTMLMethod instance at f649d050>, <Application instance at f65b0290>]
+ >>> happy.aq_inner.aq_chain
+ [<DTMLMethod instance at f649d050>, <Application instance at f65b0290>]
+
+Now we will emulate the method the publisher uses to publish the
+URL, '/Users/Barney/Songs/HappySong', fetching it in the context of
+the "Songs" folder::
+
+ >>> happy2 = app.unrestrictedTraverse('/Users/Barney/Songs/HappySong')
+ >>> happy2.aq_chain
+ [<extension class OFS.DTMLMethod.DTMLMethod at f6b0d980>, <extension class OFS.Application.Application at f6a234d0>]
+ >>> happy2.aq_inner.aq_chain
+ [<DTMLMethod instance at f651b320>, <Application instance at f65b0290>]
+
+Note that the *containment* hierarchy (fetched via
+'happy2.aq_inner.aq_chain' ) is the same as in the previous example,
+except that the *context hierarchy* includes all of the folders through
+which we have traversed.
+
+Now let's experiment with finding things via acquisition using both
+hierarchies. First, we show the case where the template cannot
+acquire 'favorite_color'::
+
+ >>> happy2(songs, {}, None)
+ " I don't have a favorite color.\n"
+
+Then, we set the 'favorite_color' attribute on one of the items in
+the *context hierarchy*, and the template is able to use it::
+
+ >>> barney.favorite_color = 'purple'
+ >>> happy2(songs, {}, None)
+ ' My favorite color is purple.\n'
+
+Summary
+=======
+
+Acquisition allows behavior to be distributed hierarchically throughout the
+system. When you add a new object to Zope, you don't need to
+specify all of its behavior, only the part of its behavior that is
+unique to that object. For the rest of its behavior, it relies on other
+objects. This means that you can change an object's behavior by
+changing where it is located in the object hierarchy. This is a
+very powerful function that gives your Zope applications
+flexibility.
+
+Acquisition is useful for providing objects with behavior that
+doesn't need to be specified by their own methods or methods found
+in their inheritance hierarchies. Acquisition is particularly
+useful for sharing information (such as headers and footers)
+between objects in different folders as well. You will see how
+you can make use of acquisition within different Zope technologies
+in upcoming chapters.
+
+A more exhaustive technical explanation of the underpinnings of
+Zope's acquisition technology is available in the `Zope Developer's
+Guide <http://www.zope.org/Documentation/ZDG/Acquisition.stx>`_.
Modified: zope2book/trunk/source/index.rst
===================================================================
--- zope2book/trunk/source/index.rst 2009-02-10 18:53:34 UTC (rev 96407)
+++ zope2book/trunk/source/index.rst 2009-02-10 19:05:30 UTC (rev 96408)
@@ -18,6 +18,7 @@
ObjectOrientation.rst
UsingZope.rst
BasicObject.rst
+ Acquisition.rst
Contributions.rst
AppendixA.rst
More information about the Checkins
mailing list