[Checkins] SVN: zdgbook/trunk/ stx to rst
Baiju M
baiju.m.mail at gmail.com
Tue Feb 17 21:26:31 EST 2009
Log message for revision 96660:
stx to rst
Changed:
D zdgbook/trunk/Acquisition.stx
A zdgbook/trunk/source/Acquisition.rst
U zdgbook/trunk/source/index.rst
-=-
Deleted: zdgbook/trunk/Acquisition.stx
===================================================================
--- zdgbook/trunk/Acquisition.stx 2009-02-18 02:17:14 UTC (rev 96659)
+++ zdgbook/trunk/Acquisition.stx 2009-02-18 02:26:31 UTC (rev 96660)
@@ -1,527 +0,0 @@
-Chapter 5: Acquisition
-
- Acquisition is a mechanism that allows objects to obtain attributes
- from their environment. It is similar to inheritance, except that,
- rather than searching an inheritance hierarchy to obtain attributes,
- a containment hierarchy is traversed.
-
- % mcdonc - June 6, 2002 12:00 pm:
- This chapter needs an explanation of the inheritedAttribute method.
-
- Introductory Example
-
- Zope implements acquisition with "Extension Class" mix-in
- classes. To use acquisition your classes must inherit from an
- acquisition base class. For example::
-
- import ExtensionClass, Acquisition
-
- class C(ExtensionClass.Base):
- color='red'
-
- class A(Acquisition.Implicit):
-
- def report(self):
- print self.color
-
- a=A()
- c=C()
- c.a=A()
-
- c.a.report() # prints 'red'
-
- d=C()
- d.color='green'
- d.a=a
-
- d.a.report() # prints 'green'
-
- a.report() # raises an attribute error
-
- The class 'A' inherits acquisition behavior from
- 'Acquisition.Implicit'. The object, 'a', "has" the color of
- objects 'c' and 'd' when it is accessed through them, but it has
- no color by itself. The object 'a' obtains attributes from its
- environment, where its environment is defined by the access path
- used to reach 'a'.
-
- Acquisition Wrappers
-
- When an object that supports acquisition is accessed through an
- extension class instance, a special object, called an acquisition
- wrapper, is returned. In the example above, the expression 'c.a'
- returns an acquisition wrapper that contains references to both
- 'c' and 'a'. It is this wrapper that performs attribute lookup in
- 'c' when an attribute cannot be found in 'a'.
-
- Acquisition wrappers provide access to the wrapped objects through
- the attributes 'aq_parent', 'aq_self', 'aq_base'. In the example
- above, the expressions::
-
- 'c.a.aq_parent is c'
-
- and::
-
- 'c.a.aq_self is a'
-
- % Anonymous User - Sep. 29, 2005 1:59 am:
- >>> c.a.aq_self is a
- False
- ..this is because "c.a" is not the same object "a" which was created earlierly. "c.a=A()" creates new object
- of class A wrapped inside object c. Check out the locations of objects "c.a" and "a".
- >>> c.a
- <__main__.A object at 0xb7e00f0c>
- >>> a
- <__main__.A object at 0xb7e0402c>
- (location mostly be different on your machine).
-
- % Anonymous User - Dec. 19, 2003 8:10 am:
- OK, this doesn't work because of the line (above):
- c.a = A()
- which creates a new object of class A.
- I suppose it should work if the above line is replaced with:
- c.a = a
-
- % Anonymous User - May 25, 2003 12:13 pm:
- Hmm. Mine isn't doing this. Here's some pasted output:
- [snip]
- AttributeError: color
- >>> c.a.aq_parent is c
- 1
- >>> c.a.aq_self is a
- 0
-
- both evaluate to true, but the expression::
-
- 'c.a is a'
-
- evaluates to false, because the expression 'c.a' evaluates to an
- acquisition wrapper around 'c' and 'a', not 'a' itself.
-
- The attribute 'aq_base' is similar to 'aq_self'. Wrappers may be
- nested and 'aq_self' may be a wrapped object. The 'aq_base'
- attribute is the underlying object with all wrappers removed.
-
- You can manually wrap an instance of an object that inherits from
- an acquisition base class by using its '__of__' method. For
- example::
-
- class A(Acquisition.Implicit):
- pass
-
- a=A()
- a.color='red'
- b=A()
- a.b=b
-
- print b.__of__(a).color # prints red
-
- % Anonymous User - Apr. 5, 2003 11:19 pm:
- Why the a.b=b here? Surely that statement should be omitted because it only confuses the issue.
- b.__of__(a).color will still return 'red' without it. The entire point of __of__() is to provide a context
- for an object, b in this case, and saying a.b=b also provides this context.
-
- The expression 'b.__of__(a)' wraps 'b' in an acquisition wrapper
- explicitly, and returns the acquisition wrapper. The 'color'
- attrribute of 'a' is found via acquisition when this expression
- is executed.
-
- % Anonymous User - Nov. 8, 2002 11:54 pm:
- i really like to see the code of __of__. Its not python, is it?
- what exactly is an acquisition wrapper?
-
- Explicit and Implicit Acquisition
-
- Two styles of acquisition are supported: implicit and explicit
- acquisition.
-
- Implicit acquisition
-
- Implicit acquisition is so named because it searches for
- attributes from the environment automatically whenever an
- attribute cannot be obtained directly from an object or through
- inheritance.
-
- An attribute can be implicitly acquired if its name does not
- begin with an underscore.
-
- To support implicit acquisition, your class should inherit from
- the mix-in class 'Acquisition.Implicit'.
-
- Explicit Acquisition
-
- When explicit acquisition is used, attributes are not
- automatically obtained from the environment. Instead, the
- method 'aq_acquire' must be used. For example::
-
- print c.a.aq_acquire('color')
-
- To support explicit acquisition, your class should inherit from
- the mix-in class 'Acquisition.Explicit'.
-
- % Anonymous User - Feb. 28, 2002 4:55 pm - Meaning that, in the above example, class A, of which a is an instance, should inherit from Acquisition.Implicit.
-
- Controlling Acquisition
-
- A class (or instance) can provide attribute by attribute control
- over acquisition. Your should subclass from
- 'Acquisition.Explicit', and set all attributes that should be
- acquired to the special value 'Acquisition.Acquired'. Setting
- an attribute to this value also allows inherited attributes to
- be overridden with acquired ones. For example::
-
- class C(Acquisition.Explicit):
- id=1
- secret=2
- color=Acquisition.Acquired
- __roles__=Acquisition.Acquired
-
- The *only* attributes that are automatically acquired from
- containing objects are 'color', and '__roles__'. Note that the
- '__roles__' attribute is acquired even though its name begins
- with an underscore. In fact, the special 'Acquisition.Acquired'
- value can be used in 'Acquisition.Implicit' objects to
- implicitly acquire selected objects that smell like private
- objects.
-
- Sometimes, you want to dynamically make an implicitly acquiring
- object acquire explicitly. You can do this by getting the object's
- 'aq_explicit' attribute. This attribute provides the object with
- an explicit wrapper that places the original implicit wrapper.
-
- Filtered Acquisition
-
- The acquisition method, 'aq_acquire', accepts two optional
- arguments. The first of the additional arguments is a
- "filtering" function that is used when considering whether to
- acquire an object. The second of the additional arguments is an
- object that is passed as extra data when calling the filtering
- function and which defaults to 'None'. The filter function is
- called with five arguments:
-
- - The object that the 'aq_acquire' method was called on,
-
- - The object where an object was found,
-
- - The name of the object, as passed to 'aq_acquire',
-
- - The object found, and
-
- - The extra data passed to 'aq_acquire'.
-
- If the filter returns a true object that the object found is
- returned, otherwise, the acquisition search continues.
-
- For example, in::
-
- from Acquisition import Explicit
-
- class HandyForTesting:
- def __init__(self, name):
- self.name=name
- def __str__(self):
- return "%s(%s)" % (self.name, self.__class__.__name__)
- __repr__=__str__
-
- class E(Explicit, HandyForTesting): pass
-
- class Nice(HandyForTesting):
- isNice=1
- def __str__(self):
- return HandyForTesting.__str__(self)+' and I am nice!'
- __repr__=__str__
-
- a=E('a')
- a.b=E('b')
- a.b.c=E('c')
- a.p=Nice('spam')
- a.b.p=E('p')
-
- def find_nice(self, ancestor, name, object, extra):
- return hasattr(object,'isNice') and object.isNice
-
- print a.b.c.aq_acquire('p', find_nice)
-
- The filtered acquisition in the last line skips over the first
- attribute it finds with the name 'p', because the attribute
- doesn't satisfy the condition given in the filter. The output of
- the last line is::
-
- spam(Nice) and I am nice!
-
- Filtered acquisition is rarely used in Zope.
-
- Acquiring from Context
-
- Normally acquisition allows objects to acquire data from their
- containers. However an object can acquire from objects that aren't
- its containers.
-
- Most of the example's we've seen so far show establishing of an
- acquisition *context* using 'getattr' symanitics. For example,
- 'a.b' is a reference to 'b' in the context of 'a'.
-
- % Anonymous User - Oct. 9, 2002 11:40 am:
- Typos.
- s/example's/examples/
- s/symanitics/semantics/
-
- You can also manuallyset acquisition context using the '__of__'
- method. For example::
-
- from Acquisition import Implicit
- class C(Implicit): pass
- a=C()
- b=C()
- a.color="red"
- print b.__of__(a).color # prints red
-
- % Anonymous User - Sep. 2, 2002 12:38 pm:
- s/manuallyset/manually set/
-
- In this case, 'a' does not contain 'b', but it is put in 'b''s
- context using the '__of__' method.
-
- Here's another subtler example that shows how you can construct an
- acquisition context that includes non-container objects::
-
- from Acquisition import Implicit
-
- class C(Implicit):
- def __init__(self, name):
- self.name=name
-
- a=C("a")
- a.b=C("b")
- a.b.color="red"
- a.x=C("x")
-
- print a.b.x.color # prints red
-
- Even though 'b' does not contain 'x', 'x' can acquire the 'color'
- attribute from 'b'. This works because in this case, 'x' is
- accessed in the context of 'b' even though it is not contained by
- 'b'.
-
- Here acquisition context is defined by the objects used to access
- another object.
-
- Containment Before Context
-
- If in the example above suppose both 'a' and 'b' have an
- 'color' attribute::
-
- a=C("a")
- a.color="green"
- a.b=C("b")
- a.b.color="red"
- a.x=C("x")
-
- print a.b.x.color # prints green
-
- % Anonymous User - Nov. 21, 2003 5:04 am:
- what i print is :
- Traceback (most recent call last):
- File "<stdin>", line 1, in ?
- AttributeError: x
-
- % Anonymous User - Nov. 21, 2003 5:37 am:
- oh, forget the last comment. sorry, i am wrong.
-
- Why does 'a.b.x.color' acquire 'color' from 'a' and not from 'b'?
- The answer is that an object acquires from its containers before
- non-containers in its context.
-
- To see why consider this example in terms of expressions using the
- '__of__' method::
-
- a.x -> x.__of__(a)
-
- a.b -> b.__of__(a)
-
- a.b.x -> x.__of__(a).__of__(b.__of__(a))
-
- Keep in mind that attribute lookup in a wrapper is done by trying
- to look up the attribute in the wrapped object first and then in
- the parent object. So in the expressions above proceeds from left
- to right.
-
- % Anonymous User - Feb. 28, 2002 6:07 pm - It looks like it should be stated a.b.x -> x.__of__(b.__of__(a)), but maybe I'm not really understanding this.
-
- % Anonymous User - July 15, 2004 12:14 pm:
- I think the reason that it's this way is because when you look for x in b.__of__(a), you try from left to
- right. However, b doesn't contain an x, so you end up with the x.__of__(a) which is contained in the
- b.__of__(a).
-
- The upshot of these rules is that attributes are looked up by
- containment before context.
-
- This rule holds true also for more complex examples. For example,
- 'a.b.c.d.e.f.g.attribute' would search for 'attribute' in 'g' and
- all its containers first. (Containers are searched in order from
- the innermost parent to the outermost container.) If the attribute
- is not found in g or any of its containers, then the search moves
- to 'f' and all its containers, and so on.
-
- Additional Attributes and Methods
-
- You can use the special method 'aq_inner' to access an object
- wrapped only by containment. So in the example above::
-
- a.b.x.aq_inner
-
- is equivalent to::
-
- a.x
-
- You can find out the acquisition context of an object using the
- 'aq_chain' method like so::
-
- a.b.x.aq_chain # returns [x, b, a]
-
- You can find out if an object is in the acquisition context of
- another object using the 'aq_inContextOf' method. For example::
-
- a.b.x.aq_inContextOf(a.b) # returns 1
-
- % Anonymous User - Apr. 20, 2005 10:00 am:
- returns 0, because:
- "aq_inContextOf = <CMethod object>
- Test whether the object is currently in the context of the argument"
- and not test in the acquisition context.
-
- % Anonymous User - Apr. 20, 2005 10:02 am:
- Ok,
- a.b.x.aq_inContextOf(a.b) # returns 0
- in Zope 2.7.5 :)
-
- You can also pass an additional argument to 'aq_inContextOf' to
- indicate whether to only check containment rather than the full
- acquisition context. For example::
-
- a.b.x.aq_inContextOf(a.b, 1) # returns 0
-
- Note: as of this writing the 'aq_inContextOf' examples don't
- work. According to Jim, this is because 'aq_inContextOf' works by
- comparing object pointer addresses, which (because they are
- actually different wrapper objects) doesn't give you the expected
- results. He acknowledges that this behavior is controversial, and
- says that there is a collector entry to change it so that you
- would get the answer you expect in the above. (We just need to get
- to it).
-
- % Anonymous User - Feb. 10, 2003 2:58 pm:
- A search on collector.zope.org for aq_inContextOf returns nothing.
- Has this issue been resolved? Was there ever a collector issue for it?
- In other words, does aq_inContextOf work or not?
-
- Acquisition Module Functions
-
- In addition to using acquisition attributes and methods directly
- on objects you can use similar functions defined in the
- 'Acquisition' module. These functions have the advantage that you
- don't need to check to make sure that the object has the method or
- attribute before calling it.
-
- 'aq_acquire(object, name [, filter, extra, explicit, default, containment])' -- Acquires an object with the given name.
-
- This function can be used to explictly acquire when using
- explicit acquisition and to acquire names that wouldn't
- normally be acquired.
-
- The function accepts a number of optional
- arguments:
-
- 'filter' -- A callable filter object that is used to decide if
- an object should be acquired.
-
- The filter is called with
- five arguments:
-
- - The object that the aq_acquire method was called on,
-
- - The object where an object was found,
-
- - The name of the object, as passed to aq_acquire,
-
- - The object found, and
-
- - The extra argument passed to aq_acquire.
-
- If the filter returns a true object that the
- object found is returned, otherwise, the acquisition
- search continues.
-
- 'extra' -- extra data to be passed as the last argument to the
- filter.
-
- 'explicit' -- A flag (boolean value) indicating whether
- explicit acquisition should be used. The default value
- is true. If the flag is true, then acquisition will
- proceed regardless of whether wrappers encountered
- in the search of the acquisition hierarchy are explicit or
- implicit wrappers. If the flag is false, then parents of
- explicit wrappers are not searched.
-
- This argument is useful if you want to apply a filter without
- overriding explicit wrappers.
-
- 'default' -- A default value to return if no value can be acquired.
-
- 'containment' -- A flag indicating whether the search
- should be limited to the containment hierarchy.
-
- In addition, arguments can be provided as keywords.
-
- 'aq_base(object)' -- Return the object with all wrapping removed.
-
- 'aq_chain(object [, containment])' -- Return a list containing the object
- and it's acquisition parents. The optional argument, 'containment',
- controls whether the containment or access hierarchy is used.
-
- 'aq_get(object, name [, default, containment])' --
- Acquire an attribute, name. A default value can be provided, as
- can a flag that limits search to the containment hierarchy.
-
- 'aq_inner(object)' -- Return the object with all but the innermost
- layer of wrapping removed.
-
- 'aq_parent(object)' -- Return the acquisition parent of the object
- or 'None' if the object is unwrapped.
-
- 'aq_self(object)' -- Return the object with one layer of wrapping
- removed, unless the object is unwrapped, in which case the
- object is returned.
-
- In most cases it is more convenient to use these module functions
- instead of the acquisition attributes and methods directly.
-
- Acquisition and Methods
-
- Python methods of objects that support acquisition can use
- acquired attributes. When a Python method is called on an object
- that is wrapped by an acquisition wrapper, the wrapper is passed
- to the method as the first argument. This rule also applies to
- user-defined method types and to C methods defined in pure mix-in
- classes.
-
- Unfortunately, C methods defined in extension base classes that
- define their own data structures, cannot use aquired attributes at
- this time. This is because wrapper objects do not conform to the
- data structures expected by these methods. In practice, you will
- seldom find this a problem.
-
- Conclusion
-
- Acquisition provides a powerful way to dynamically share
- information between objects. Zope using acquisition for a number
- of its key features including security, object publishing, and
- DTML variable lookup. Acquisition also provides an elegant
- solution to the problem of circular references for many classes of
- problems. While acquisition is powerful, you should take care when
- using acquisition in your applications. The details can get
- complex, especially with the differences between acquiring from
- context and acquiring from containment.
-
- % acornet - Feb. 17, 2003 10:22 am:
- s/using/uses/
Copied: zdgbook/trunk/source/Acquisition.rst (from rev 96642, zdgbook/trunk/Acquisition.stx)
===================================================================
--- zdgbook/trunk/source/Acquisition.rst (rev 0)
+++ zdgbook/trunk/source/Acquisition.rst 2009-02-18 02:26:31 UTC (rev 96660)
@@ -0,0 +1,457 @@
+###########
+Acquisition
+###########
+
+Acquisition is a mechanism that allows objects to obtain attributes
+from their environment. It is similar to inheritance, except that,
+rather than searching an inheritance hierarchy to obtain attributes,
+a containment hierarchy is traversed.
+
+
+Introductory Example
+====================
+
+Zope implements acquisition with "Extension Class" mix-in classes. To
+use acquisition your classes must inherit from an acquisition base
+class. For example::
+
+ import ExtensionClass, Acquisition
+
+ class C(ExtensionClass.Base):
+ color = 'red'
+
+ class A(Acquisition.Implicit):
+
+ def report(self):
+ print self.color
+
+ a = A()
+ c = C()
+ c.a = A()
+
+ c.a.report() # prints 'red'
+
+ d = C()
+ d.color = 'green'
+ d.a = a
+
+ d.a.report() # prints 'green'
+
+ a.report() # raises an attribute error
+
+The class 'A' inherits acquisition behavior from
+'Acquisition.Implicit'. The object, 'a', "has" the color of objects
+'c' and 'd' when it is accessed through them, but it has no color by
+itself. The object 'a' obtains attributes from its environment,
+where its environment is defined by the access path used to reach
+'a'.
+
+Acquisition Wrappers
+====================
+
+When an object that supports acquisition is accessed through an
+extension class instance, a special object, called an acquisition
+wrapper, is returned. In the example above, the expression 'c.a'
+returns an acquisition wrapper that contains references to both 'c'
+and 'a'. It is this wrapper that performs attribute lookup in 'c'
+when an attribute cannot be found in 'a'.
+
+Acquisition wrappers provide access to the wrapped objects through
+the attributes 'aq_parent', 'aq_self', 'aq_base'. In the example
+above, the expressions::
+
+ 'c.a.aq_parent is c'
+
+and::
+
+ 'c.a.aq_self is a'
+
+
+both evaluate to true, but the expression::
+
+ 'c.a is a'
+
+evaluates to false, because the expression 'c.a' evaluates to an
+acquisition wrapper around 'c' and 'a', not 'a' itself.
+
+The attribute 'aq_base' is similar to 'aq_self'. Wrappers may be
+nested and 'aq_self' may be a wrapped object. The 'aq_base'
+attribute is the underlying object with all wrappers removed.
+
+You can manually wrap an instance of an object that inherits from an
+acquisition base class by using its '__of__' method. For example::
+
+ class A(Acquisition.Implicit):
+ pass
+
+ a = A()
+ a.color = 'red'
+ b = A()
+ a.b = b
+
+ print b.__of__(a).color # prints red
+
+
+The expression 'b.__of__(a)' wraps 'b' in an acquisition wrapper
+explicitly, and returns the acquisition wrapper. The 'color'
+attrribute of 'a' is found via acquisition when this expression is
+executed.
+
+
+Explicit and Implicit Acquisition
+=================================
+
+Two styles of acquisition are supported: implicit and explicit
+acquisition.
+
+Implicit acquisition
+--------------------
+
+Implicit acquisition is so named because it searches for
+attributes from the environment automatically whenever an
+attribute cannot be obtained directly from an object or through
+inheritance.
+
+An attribute can be implicitly acquired if its name does not
+begin with an underscore.
+
+To support implicit acquisition, your class should inherit from
+the mix-in class 'Acquisition.Implicit'.
+
+Explicit Acquisition
+--------------------
+
+When explicit acquisition is used, attributes are not automatically
+obtained from the environment. Instead, the method 'aq_acquire' must
+be used. For example::
+
+ print c.a.aq_acquire('color')
+
+To support explicit acquisition, your class should inherit from the
+mix-in class 'Acquisition.Explicit'.
+
+Controlling Acquisition
+=======================
+
+A class (or instance) can provide attribute by attribute control over
+acquisition. Your should subclass from 'Acquisition.Explicit', and
+set all attributes that should be acquired to the special value
+'Acquisition.Acquired'. Setting an attribute to this value also
+allows inherited attributes to be overridden with acquired ones. For
+example::
+
+ class C(Acquisition.Explicit):
+ id=1
+ secret=2
+ color=Acquisition.Acquired
+ __roles__=Acquisition.Acquired
+
+The *only* attributes that are automatically acquired from containing
+objects are 'color', and '__roles__'. Note that the '__roles__'
+attribute is acquired even though its name begins with an underscore.
+In fact, the special 'Acquisition.Acquired' value can be used in
+'Acquisition.Implicit' objects to implicitly acquire selected objects
+that smell like private objects.
+
+Sometimes, you want to dynamically make an implicitly acquiring
+object acquire explicitly. You can do this by getting the object's
+'aq_explicit' attribute. This attribute provides the object with an
+explicit wrapper that places the original implicit wrapper.
+
+Filtered Acquisition
+====================
+
+The acquisition method, 'aq_acquire', accepts two optional
+arguments. The first of the additional arguments is a "filtering"
+function that is used when considering whether to acquire an object.
+The second of the additional arguments is an object that is passed as
+extra data when calling the filtering function and which defaults to
+'None'. The filter function is called with five arguments:
+
+- The object that the 'aq_acquire' method was called on,
+
+- The object where an object was found,
+
+- The name of the object, as passed to 'aq_acquire',
+
+- The object found, and
+
+- The extra data passed to 'aq_acquire'.
+
+If the filter returns a true object that the object found is
+returned, otherwise, the acquisition search continues.
+
+For example, in::
+
+ from Acquisition import Explicit
+
+ class HandyForTesting:
+ def __init__(self, name):
+ self.name = name
+ def __str__(self):
+ return "%s(%s)" % (self.name, self.__class__.__name__)
+ __repr__ = __str__
+
+ class E(Explicit, HandyForTesting): pass
+
+ class Nice(HandyForTesting):
+ isNice = 1
+ def __str__(self):
+ return HandyForTesting.__str__(self) + ' and I am nice!'
+ __repr__ = __str__
+
+ a = E('a')
+ a.b = E('b')
+ a.b.c = E('c')
+ a.p = Nice('spam')
+ a.b.p = E('p')
+
+ def find_nice(self, ancestor, name, object, extra):
+ return hasattr(object,'isNice') and object.isNice
+
+ print a.b.c.aq_acquire('p', find_nice)
+
+The filtered acquisition in the last line skips over the first
+attribute it finds with the name 'p', because the attribute doesn't
+satisfy the condition given in the filter. The output of the last
+line is::
+
+ spam(Nice) and I am nice!
+
+Filtered acquisition is rarely used in Zope.
+
+Acquiring from Context
+======================
+
+Normally acquisition allows objects to acquire data from their
+containers. However an object can acquire from objects that aren't
+its containers.
+
+Most of the example's we've seen so far show establishing of an
+acquisition *context* using 'getattr' symanitics. For example, 'a.b'
+is a reference to 'b' in the context of 'a'.
+
+
+You can also manuallyset acquisition context using the '__of__'
+method. For example::
+
+ from Acquisition import Implicit
+ class C(Implicit): pass
+ a = C()
+ b = C()
+ a.color = "red"
+ print b.__of__(a).color # prints red
+
+In this case, 'a' does not contain 'b', but it is put in 'b''s
+context using the '__of__' method.
+
+Here's another subtler example that shows how you can construct an
+acquisition context that includes non-container objects::
+
+ from Acquisition import Implicit
+
+ class C(Implicit):
+ def __init__(self, name):
+ self.name = name
+
+ a = C("a")
+ a.b = C("b")
+ a.b.color = "red"
+ a.x = C("x")
+
+ print a.b.x.color # prints red
+
+Even though 'b' does not contain 'x', 'x' can acquire the 'color'
+attribute from 'b'. This works because in this case, 'x' is accessed
+in the context of 'b' even though it is not contained by 'b'.
+
+Here acquisition context is defined by the objects used to access
+another object.
+
+Containment Before Context
+==========================
+
+If in the example above suppose both 'a' and 'b' have an 'color'
+attribute::
+
+ a = C("a")
+ a.color = "green"
+ a.b = C("b")
+ a.b.color = "red"
+ a.x = C("x")
+
+ print a.b.x.color # prints green
+
+
+Why does 'a.b.x.color' acquire 'color' from 'a' and not from 'b'?
+The answer is that an object acquires from its containers before
+non-containers in its context.
+
+To see why consider this example in terms of expressions using the
+'__of__' method::
+
+ a.x -> x.__of__(a)
+
+ a.b -> b.__of__(a)
+
+ a.b.x -> x.__of__(a).__of__(b.__of__(a))
+
+Keep in mind that attribute lookup in a wrapper is done by trying to
+look up the attribute in the wrapped object first and then in the
+parent object. So in the expressions above proceeds from left to
+right.
+
+
+The upshot of these rules is that attributes are looked up by
+containment before context.
+
+This rule holds true also for more complex examples. For example,
+'a.b.c.d.e.f.g.attribute' would search for 'attribute' in 'g' and all
+its containers first. (Containers are searched in order from the
+innermost parent to the outermost container.) If the attribute is not
+found in g or any of its containers, then the search moves to 'f' and
+all its containers, and so on.
+
+Additional Attributes and Methods
+=================================
+
+You can use the special method 'aq_inner' to access an object wrapped
+only by containment. So in the example above::
+
+ a.b.x.aq_inner
+
+is equivalent to::
+
+ a.x
+
+You can find out the acquisition context of an object using the
+'aq_chain' method like so::
+
+ a.b.x.aq_chain # returns [x, b, a]
+
+You can find out if an object is in the acquisition context of
+another object using the 'aq_inContextOf' method. For example::
+
+ a.b.x.aq_inContextOf(a.b) # returns 1
+
+
+You can also pass an additional argument to 'aq_inContextOf' to
+indicate whether to only check containment rather than the full
+acquisition context. For example::
+
+ a.b.x.aq_inContextOf(a.b, 1) # returns 0
+
+Note: as of this writing the 'aq_inContextOf' examples don't
+work. According to Jim, this is because 'aq_inContextOf' works by
+comparing object pointer addresses, which (because they are actually
+different wrapper objects) doesn't give you the expected results. He
+acknowledges that this behavior is controversial, and says that there
+is a collector entry to change it so that you would get the answer
+you expect in the above. (We just need to get to it).
+
+
+Acquisition Module Functions
+----------------------------
+
+In addition to using acquisition attributes and methods directly on
+objects you can use similar functions defined in the 'Acquisition'
+module. These functions have the advantage that you don't need to
+check to make sure that the object has the method or attribute before
+calling it.
+
+'aq_acquire(object, name [, filter, extra, explicit, default, containment])' -- Acquires an object with the given name.
+
+This function can be used to explictly acquire when using explicit
+acquisition and to acquire names that wouldn't normally be acquired.
+
+The function accepts a number of optional arguments:
+
+- 'filter' -- A callable filter object that is used to decide if an
+ object should be acquired.
+
+ The filter is called with five arguments:
+
+ - The object that the aq_acquire method was called on,
+
+ - The object where an object was found,
+
+ - The name of the object, as passed to aq_acquire,
+
+ - The object found, and
+
+ - The extra argument passed to aq_acquire.
+
+ If the filter returns a true object that the object found is
+ returned, otherwise, the acquisition search continues.
+
+- 'extra' -- extra data to be passed as the last argument to the
+ filter.
+
+- 'explicit' -- A flag (boolean value) indicating whether explicit
+ acquisition should be used. The default value is true. If the flag
+ is true, then acquisition will proceed regardless of whether
+ wrappers encountered in the search of the acquisition hierarchy are
+ explicit or implicit wrappers. If the flag is false, then parents
+ of explicit wrappers are not searched.
+
+ This argument is useful if you want to apply a filter without
+ overriding explicit wrappers.
+
+- 'default' -- A default value to return if no value can be acquired.
+
+- 'containment' -- A flag indicating whether the search should be
+ limited to the containment hierarchy.
+
+In addition, arguments can be provided as keywords.
+
+- 'aq_base(object)' -- Return the object with all wrapping removed.
+
+- 'aq_chain(object [, containment])' -- Return a list containing the
+ object and it's acquisition parents. The optional argument,
+ 'containment', controls whether the containment or access hierarchy
+ is used.
+
+- 'aq_get(object, name [, default, containment])' -- Acquire an
+ attribute, name. A default value can be provided, as can a flag
+ that limits search to the containment hierarchy.
+
+- 'aq_inner(object)' -- Return the object with all but the innermost
+ layer of wrapping removed.
+
+- 'aq_parent(object)' -- Return the acquisition parent of the object
+ or 'None' if the object is unwrapped.
+
+- 'aq_self(object)' -- Return the object with one layer of wrapping
+ removed, unless the object is unwrapped, in which case the object
+ is returned.
+
+In most cases it is more convenient to use these module functions
+instead of the acquisition attributes and methods directly.
+
+Acquisition and Methods
+=======================
+
+Python methods of objects that support acquisition can use acquired
+attributes. When a Python method is called on an object that is
+wrapped by an acquisition wrapper, the wrapper is passed to the
+method as the first argument. This rule also applies to user-defined
+method types and to C methods defined in pure mix-in classes.
+
+Unfortunately, C methods defined in extension base classes that
+define their own data structures, cannot use aquired attributes at
+this time. This is because wrapper objects do not conform to the
+data structures expected by these methods. In practice, you will
+seldom find this a problem.
+
+Conclusion
+==========
+
+Acquisition provides a powerful way to dynamically share information
+between objects. Zope using acquisition for a number of its key
+features including security, object publishing, and DTML variable
+lookup. Acquisition also provides an elegant solution to the problem
+of circular references for many classes of problems. While
+acquisition is powerful, you should take care when using acquisition
+in your applications. The details can get complex, especially with
+the differences between acquiring from context and acquiring from
+containment.
Property changes on: zdgbook/trunk/source/Acquisition.rst
___________________________________________________________________
Added: svn:mergeinfo
+
Modified: zdgbook/trunk/source/index.rst
===================================================================
--- zdgbook/trunk/source/index.rst 2009-02-18 02:17:14 UTC (rev 96659)
+++ zdgbook/trunk/source/index.rst 2009-02-18 02:26:31 UTC (rev 96660)
@@ -16,6 +16,7 @@
ObjectPublishing.rst
Products.rst
ZODBPersistentComponents.rst
+ Acquisition.rst
AppendixA.rst
AppendixB.rst
More information about the Checkins
mailing list