Merge lp:~salgado/lazr.delegates/extend-passthrough into lp:lazr.delegates

Proposed by Guilherme Salgado
Status: Merged
Approved by: Gary Poster
Approved revision: 6
Merged at revision: 5
Proposed branch: lp:~salgado/lazr.delegates/extend-passthrough
Merge into: lp:lazr.delegates
Diff against target: 98 lines (+54/-7)
2 files modified
src/lazr/delegates/README.txt (+37/-3)
src/lazr/delegates/_delegates.py (+17/-4)
To merge this branch: bzr merge lp:~salgado/lazr.delegates/extend-passthrough
Reviewer Review Type Date Requested Status
Gary Poster Approve
Review via email: mp+30084@code.launchpad.net

Description of the change

Extend Passthrough so that it takes an extra argument to which the context is adapted before getting/setting the attribute

This is going to be used in https://code.edge.launchpad.net/~salgado/lazr.restful/extension-interfaces

To post a comment you must log in.
6. By Guilherme Salgado

A few tweaks suggested by Gary

Revision history for this message
Gary Poster (gary) wrote :

merge-conditional

Looks great. A few remaining trivial cleanups.

orig_interface -> adaptation in "Passthrough's third argument (orig_interface) is optional..." (src/lazr/delegates/README.txt)

"...(although in practice anything that provides a __call__() method will do)..." -> "...(although in practice any callable will do)..." (src/lazr/delegates/README.txt)

"If adaptation is not None, the context is adapted into it before getting/setting the attribute." -> "If the ``adaptation`` argument is not None, it should be a callable. It will be called with the context, and should return an object that will have the delegated attribute. The ``adaptation`` argument is expected to be used with an interface, to adapt the context." (src/lazr/delegates/_delegates.py)

Thank you!

Gary

review: Approve
7. By Guilherme Salgado

A couple other changes suggested by Gary

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/lazr/delegates/README.txt'
--- src/lazr/delegates/README.txt 2009-04-14 16:07:52 +0000
+++ src/lazr/delegates/README.txt 2010-07-16 13:16:40 +0000
@@ -193,9 +193,9 @@
193193
194The Passthrough class is the implementation machinery of ``delegates()``. It194The Passthrough class is the implementation machinery of ``delegates()``. It
195uses the descriptor protocol to implement the delegation behaviour provided by195uses the descriptor protocol to implement the delegation behaviour provided by
196``delegates()``. It takes two arguments: the name of the attribute that is196``delegates()``. It takes at least two arguments: the name of the attribute
197delegated, and the name of the attribute containing the object to which to197that is delegated, and the name of the attribute containing the object to
198delegate.198which to delegate.
199199
200To illustrate, p and p2 are two Passthrough instances that use the200To illustrate, p and p2 are two Passthrough instances that use the
201instance assigned to 'mycontext' to call the 'foo' attribute and201instance assigned to 'mycontext' to call the 'foo' attribute and
@@ -247,6 +247,40 @@
247 ...247 ...
248 NotImplementedError248 NotImplementedError
249249
250Passthrough's third argument (adaptation) is optional and, when provided,
251should be a zope.interface.Interface subclass (although in practice any
252callable will do) to which the instance is adapted before getting/setting the
253delegated attribute.
254
255 # HasNoFoo does not have a .foo attribute...
256 >>> class HasNoFoo(object):
257 ... _foo = 1
258 >>> no_foo = HasNoFoo()
259
260 # ... but IHasFooAdapter uses HasNoFoo._foo to provide its own .foo, so it
261 # works like an adapter for HasNoFoo into some interface that provides
262 # a 'foo' attribute.
263 >>> class IHasFooAdapter(object):
264 ... def __init__(self, inst):
265 ... self.inst = inst
266 ... def _get_foo(self):
267 ... return self.inst._foo
268 ... def _set_foo(self, value):
269 ... self.inst._foo = value
270 ... foo = property(_get_foo, _set_foo)
271
272 >>> class Example(object):
273 ... context = no_foo
274
275 >>> p = Passthrough('foo', 'context', adaptation=IHasFooAdapter)
276 >>> e = Example()
277 >>> p.__get__(e)
278 1
279 >>> p.__set__(e, 2)
280 >>> p.__get__(e)
281 2
282
283
250===============284===============
251Other Documents285Other Documents
252===============286===============
253287
=== modified file 'src/lazr/delegates/_delegates.py'
--- src/lazr/delegates/_delegates.py 2009-04-14 16:07:52 +0000
+++ src/lazr/delegates/_delegates.py 2010-07-16 13:16:40 +0000
@@ -108,19 +108,32 @@
108108
109109
110class Passthrough:110class Passthrough:
111 """Call the delegated class for the decorator class."""111 """Call the delegated class for the decorator class.
112 def __init__(self, name, contextvar):112
113 If the ``adaptation`` argument is not None, it should be a callable. It
114 will be called with the context, and should return an object that will
115 have the delegated attribute. The ``adaptation`` argument is expected to
116 be used with an interface, to adapt the context.
117 """
118 def __init__(self, name, contextvar, adaptation=None):
113 self.name = name119 self.name = name
114 self.contextvar = contextvar120 self.contextvar = contextvar
121 self.adaptation = adaptation
115122
116 def __get__(self, inst, cls=None):123 def __get__(self, inst, cls=None):
117 if inst is None:124 if inst is None:
118 return self125 return self
119 else:126 else:
120 return getattr(getattr(inst, self.contextvar), self.name)127 context = getattr(inst, self.contextvar)
128 if self.adaptation is not None:
129 context = self.adaptation(context)
130 return getattr(context, self.name)
121131
122 def __set__(self, inst, value):132 def __set__(self, inst, value):
123 setattr(getattr(inst, self.contextvar), self.name, value)133 context = getattr(inst, self.contextvar)
134 if self.adaptation is not None:
135 context = self.adaptation(context)
136 setattr(context, self.name, value)
124137
125 def __delete__(self, inst):138 def __delete__(self, inst):
126 raise NotImplementedError139 raise NotImplementedError

Subscribers

People subscribed via source and target branches