[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