~landscape/zope3/ztk-1.1.3

« back to all changes in this revision

Viewing changes to src/zope/structuredtext/regressions/Acquisition.ref

  • Committer: Sidnei da Silva
  • Date: 2010-07-05 21:07:01 UTC
  • Revision ID: sidnei.da.silva@canonical.com-20100705210701-zmqhqrbzad1mhzsl
- Reduce deps

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<html>
2
 
<head>
3
 
<title>Acquisition</title>
4
 
</head>
5
 
<body>
6
 
<h1>Acquisition</h1>
7
 
<p>  <a href="COPYRIGHT.html">Copyright (C) 1996-1998, Digital Creations</a>.</p>
8
 
<p>  Acquisition <a href="#ref1">[1]</a> is a mechanism that allows objects to obtain
9
 
  attributes from their environment.  It is similar to inheritence,
10
 
  except that, rather than traversing an inheritence hierarchy
11
 
  to obtain attributes, a containment hierarchy is traversed.</p>
12
 
<p>  The <a href="ExtensionClass.html">ExtensionClass</a>. release includes mix-in
13
 
  extension base classes that can be used to add acquisition as a
14
 
  feature to extension subclasses.  These mix-in classes use the
15
 
  context-wrapping feature of ExtensionClasses to implement
16
 
  acquisition. Consider the following example:</p>
17
 
 
18
 
<pre>
19
 
    import ExtensionClass, Acquisition
20
 
 
21
 
    class C(ExtensionClass.Base):
22
 
      color='red'
23
 
 
24
 
    class A(Acquisition.Implicit):
25
 
 
26
 
      def report(self):
27
 
        print self.color
28
 
 
29
 
    a=A()
30
 
    c=C()
31
 
    c.a=A()
32
 
 
33
 
    c.a.report() # prints 'red'
34
 
 
35
 
    d=C()
36
 
    d.color='green'
37
 
    d.a=a
38
 
 
39
 
    d.a.report() # prints 'green'
40
 
 
41
 
    a.report() # raises an attribute error
42
 
</pre>
43
 
<p>  The class <code>A</code> inherits acquisition behavior from
44
 
  <code>Acquisition.Implicit</code>.  The object, <code>a</code>, "has" the color of
45
 
  objects <code>c</code> and <code>d</code> when it is accessed through them, but it
46
 
  has no color by itself.  The object <code>a</code> obtains attributes
47
 
  from it's environment, where it's environment is defined by
48
 
  the access path used to reach <code>a</code>.</p>
49
 
<h2>  Acquisition wrappers</h2>
50
 
<p>    When an object that supports acquisition is accessed through
51
 
    an extension class instance, a special object, called an
52
 
    acquisition wrapper, is returned.  In the example above, the
53
 
    expression <code>c.a</code> returns an acquisition wrapper that
54
 
    contains references to both <code>c</code> and <code>a</code>.  It is this wrapper
55
 
    that performs attribute lookup in <code>c</code> when an attribute
56
 
    cannot be found in <code>a</code>.</p>
57
 
<p>    Aquisition wrappers provide access to the wrapped objects
58
 
    through the attributes <code>aq_parent</code>, <code>aq_self</code>, <code>aq_base</code>.  
59
 
    In the example above, the expressions:</p>
60
 
 
61
 
<pre>
62
 
       'c.a.aq_parent is c'
63
 
</pre>
64
 
<p>    and:</p>
65
 
 
66
 
<pre>
67
 
       'c.a.aq_self is a'
68
 
</pre>
69
 
<p>    both evaluate to true, but the expression:</p>
70
 
 
71
 
<pre>
72
 
       'c.a is a'
73
 
</pre>
74
 
<p>    evaluates to false, because the expression <code>c.a</code> evaluates
75
 
    to an acquisition wrapper around <code>c</code> and <code>a</code>, not <code>a</code> itself.</p>
76
 
<p>    The attribute <code>aq_base</code> is similar to <code>aq_self</code>.  Wrappers may be
77
 
    nested and <code>aq_self</code> may be a wrapped object.  The <code>aq_base</code>
78
 
    attribute is the underlying object with all wrappers removed.</p>
79
 
<h2>  Acquisition Control</h2>
80
 
<p>    Two styles of acquisition are supported in the current
81
 
    ExtensionClass release, implicit and explicit aquisition.</p>
82
 
<h3>    Implicit acquisition</h3>
83
 
<p>      Implicit acquisition is so named because it searches for
84
 
      attributes from the environment automatically whenever an
85
 
      attribute cannot be obtained directly from an object or
86
 
      through inheritence.</p>
87
 
<p>      An attribute may be implicitly acquired if it's name does
88
 
      not begin with an underscore, <code>_</code>.</p>
89
 
<p>      To support implicit acquisition, an object should inherit
90
 
      from the mix-in class <code>Acquisition.Implicit</code>.</p>
91
 
<h3>    Explicit Acquisition</h3>
92
 
<p>      When explicit acquisition is used, attributes are not
93
 
      automatically obtained from the environment.  Instead, the
94
 
      method <code>aq_aquire</code> must be used, as in:</p>
95
 
 
96
 
<pre>
97
 
        print c.a.aq_acquire('color')
98
 
</pre>
99
 
<p>      To support explicit acquisition, an object should inherit
100
 
      from the mix-in class <code>Acquisition.Explicit</code>.</p>
101
 
<h3>    Controlled Acquisition</h3>
102
 
<p>      A class (or instance) can provide attribute by attribute control
103
 
      over acquisition.  This is done by:</p>
104
 
 
105
 
<ul>
106
 
<li>subclassing from <code>Acquisition.Explicit</code>, and</li>
107
 
<li>setting all attributes that should be acquired to the special
108
 
        value: <code>Acquisition.Acquired</code>.  Setting an attribute to this
109
 
        value also allows inherited attributes to be overridden with
110
 
        acquired ones.<p>        For example, in:</p>
111
 
 
112
 
<pre>
113
 
          class C(Acquisition.Explicit):
114
 
             id=1
115
 
             secret=2
116
 
             color=Acquisition.Acquired
117
 
             __roles__=Acquisition.Acquired
118
 
</pre>
119
 
<p>        The <em>only</em> attributes that are automatically acquired from
120
 
        containing objects are <code>color</code>, and <code>__roles__</code>.  Note also
121
 
        that the <code>__roles__</code> attribute is acquired even though it's
122
 
        name begins with an underscore.  In fact, the special
123
 
        <code>Acquisition.Acquired</code> value can be used in
124
 
        <code>Acquisition.Implicit</code> objects to implicitly acquire selected
125
 
        objects that smell like private objects.</p>
126
 
</li>
127
 
 
128
 
</ul>
129
 
<h3>    Filtered Acquisition</h3>
130
 
<p>      The acquisition method, <code>aq_acquire</code>, accepts two optional
131
 
      arguments. The first of the additional arguments is a
132
 
      "filtering" function that is used when considering whether to
133
 
      acquire an object.  The second of the additional arguments is an
134
 
      object that is passed as extra data when calling the filtering
135
 
      function and which defaults to <code>None</code>.</p>
136
 
<p>      The filter function is called with five arguments:</p>
137
 
 
138
 
<ul>
139
 
<li>The object that the <code>aq_acquire</code> method was called on,</li>
140
 
<li>The object where an object was found,</li>
141
 
<li>The name of the object, as passed to <code>aq_acquire</code>,</li>
142
 
<li>The object found, and</li>
143
 
<li>The extra data passed to <code>aq_acquire</code>.</li>
144
 
 
145
 
</ul>
146
 
<p>      If the filter returns a true object that the object found is
147
 
      returned, otherwise, the acquisition search continues.</p>
148
 
<p>      For example, in:</p>
149
 
 
150
 
<pre>
151
 
        from Acquisition import Explicit
152
 
 
153
 
        class HandyForTesting:
154
 
            def __init__(self, name): self.name=name
155
 
            def __str__(self):
156
 
                return "%s(%s)" % (self.name, self.__class__.__name__)
157
 
            __repr__=__str__
158
 
 
159
 
        class E(Explicit, HandyForTesting): pass
160
 
 
161
 
        class Nice(HandyForTesting):
162
 
            isNice=1
163
 
            def __str__(self):
164
 
                return HandyForTesting.__str__(self)+' and I am nice!'
165
 
            __repr__=__str__
166
 
 
167
 
        a=E('a')
168
 
        a.b=E('b')
169
 
        a.b.c=E('c')
170
 
        a.p=Nice('spam')
171
 
        a.b.p=E('p')
172
 
 
173
 
        def find_nice(self, ancestor, name, object, extra):
174
 
            return hasattr(object,'isNice') and object.isNice
175
 
 
176
 
        print a.b.c.aq_acquire('p', find_nice)
177
 
</pre>
178
 
<p>      The filtered acquisition in the last line skips over the first
179
 
      attribute it finds with the name <code>p</code>, because the attribute
180
 
      doesn't satisfy the condition given in the filter. The output of
181
 
      the last line is:</p>
182
 
 
183
 
<pre>
184
 
        spam(Nice) and I am nice!
185
 
</pre>
186
 
<h2>  Acquisition and methods</h2>
187
 
<p>    Python methods of objects that support acquisition can use
188
 
    acquired attributes as in the <code>report</code> method of the first example
189
 
    above.  When a Python method is called on an object that is
190
 
    wrapped by an acquisition wrapper, the wrapper is passed to the
191
 
    method as the first argument.  This rule also applies to
192
 
    user-defined method types and to C methods defined in pure mix-in
193
 
    classes.</p>
194
 
<p>    Unfortunately, C methods defined in extension base classes that
195
 
    define their own data structures, cannot use aquired attributes at
196
 
    this time.  This is because wrapper objects do not conform to the
197
 
    data structures expected by these methods.</p>
198
 
<h2>  Acquiring Acquiring objects</h2>
199
 
<p>    Consider the following example:</p>
200
 
 
201
 
<pre>
202
 
      from Acquisition import Implicit
203
 
 
204
 
      class C(Implicit):
205
 
          def __init__(self, name): self.name=name
206
 
          def __str__(self):
207
 
              return "%s(%s)" % (self.name, self.__class__.__name__)
208
 
          __repr__=__str__
209
 
 
210
 
      a=C("a")
211
 
      a.b=C("b")
212
 
      a.b.pref="spam"
213
 
      a.b.c=C("c")
214
 
      a.b.c.color="red"
215
 
      a.b.c.pref="eggs"
216
 
      a.x=C("x")
217
 
 
218
 
      o=a.b.c.x
219
 
</pre>
220
 
<p>    The expression <code>o.color</code> might be expected to return <code>"red"</code>. In
221
 
    earlier versions of ExtensionClass, however, this expression
222
 
    failed.  Acquired acquiring objects did not acquire from the
223
 
    environment they were accessed in, because objects were only
224
 
    wrapped when they were first found, and were not rewrapped as they
225
 
    were passed down the acquisition tree.</p>
226
 
<p>    In the current release of ExtensionClass, the expression "o.color"
227
 
    does indeed return <code>"red"</code>.</p>
228
 
<p>    When searching for an attribute in <code>o</code>, objects are searched in
229
 
    the order <code>x</code>, <code>a</code>, <code>b</code>, <code>c</code>. So, for example, the expression,
230
 
    <code>o.pref</code> returns <code>"spam"</code>, not <code>"eggs"</code>.  In earlier releases of
231
 
    ExtensionClass, the attempt to get the <code>pref</code> attribute from <code>o</code>
232
 
    would have failed.</p>
233
 
<p>    If desired, the current rules for looking up attributes in complex
234
 
    expressions can best be understood through repeated application of
235
 
    the <code>__of__</code> method:</p>
236
 
<dl>
237
 
<dt>    <code>a.x</code></dt>
238
 
<dd><code>x.__of__(a)</code></dd>
239
 
<dt>    <code>a.b</code></dt>
240
 
<dd><code>b.__of__(a)</code></dd>
241
 
<dt>    <code>a.b.x</code></dt>
242
 
<dd><code>x.__of__(a).__of__(b.__of__(a))</code></dd>
243
 
<dt>    <code>a.b.c</code></dt>
244
 
<dd><code>c.__of__(b.__of__(a))</code></dd>
245
 
<dt>    <code>a.b.c.x</code></dt>
246
 
<dd><code>x.__of__(a).__of__(b.__of__(a)).__of__(c.__of__(b.__of__(a)))</code></dd>
247
 
</dl>
248
 
<p>    and by keeping in mind that attribute lookup in a wrapper
249
 
    is done by trying to lookup the attribute in the wrapped object
250
 
    first and then in the parent object.  In the expressions above
251
 
    involving the <code>__of__</code> method, lookup proceeds from left to right.</p>
252
 
<p>    Note that heuristics are used to avoid most of the repeated
253
 
    lookups. For example, in the expression: <code>a.b.c.x.foo</code>, the object
254
 
    <code>a</code> is searched no more than once, even though it is wrapped three
255
 
    times.</p>
256
 
<p><a name="ref1">[1]</a> Gil, J., Lorenz, D., 
257
 
   <a href="http://www.bell-labs.com/people/cope/oopsla/Oopsla96TechnicalProgramAbstracts.html#GilLorenz">Environmental Acquisition--A New Inheritance-Like Abstraction Mechanism</a>, 
258
 
   OOPSLA '96 Proceedings, ACM SIG-PLAN, October, 1996</p>
259
 
</body>
260
 
</html>