Well,  I think your approach would lead to better replability (e.g., dir()), and be more efficient. I don&#39;t like the special-casing of None, though; it&#39;d be better to have a list of methods not to override the return value of, probably, so that the default is to support chaining. The simple __getattr__ every time approach has the benefit of being simple; although perhaps it&#39;d be worthwhile to also do   setattr(self, obj, myf) before returning myf.<br>
<br>By the way, does inspect.isbuiltin  work for your decorator? I can&#39;t get pycairo to build, but it&#39;s possible you should be checking isinstance(foo, (types.MethodType, types.FunctionType, types.BuiltinFunctionType, types.BuiltinMethodType))<br>
<br>(And of course that doesn&#39;t handle classes that are themselves callable).<br><br><br><div class="gmail_quote">On Fri, Jun 15, 2012 at 12:04 AM, David Ginsburg <span dir="ltr">&lt;<a href="mailto:dav9dg@gmail.com" target="_blank">dav9dg@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>Sorry for all the messages, but what I was doing was overkill.</div>After re-reading Brian&#39;s message I suppose you could just do this:<div>
<br></div><div><div class="im"><div>def __getattr__(self, name):</div><div>    def myf(*args, **kwargs):</div>
</div><div>      to_return = getattr(self.ctx, name)(*args, **kwargs)</div><div class="im"><div>      if to_return is None:</div><div>        to_return = self</div><div>      return to_return</div></div><div>    return myf</div>
</div><div><br></div>
<div>cheers,</div><div>David<div><div class="h5"><br><br><div class="gmail_quote">On Fri, Jun 15, 2012 at 12:01 AM, David Ginsburg <span dir="ltr">&lt;<a href="mailto:dav9dg@gmail.com" target="_blank">dav9dg@gmail.com</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hmm, so I just tried to actually run this and for some reason inspect.getmembers(cairo.Context, predicate=inspect.ismethod) returns an empty list.<div>

<br></div><div>Here&#39;s my ugly workaround:</div><div><br></div><div>
<div><div><div>def make_chainable_context(cls):</div><div><br></div><div>    def return_self_decorator(func):</div><div>        </div><div>        def wrapper(self, *args, **kwargs):</div><div>            to_return = func(self, *args, **kwargs)</div>


<div>            if to_return is None:</div><div>                to_return = self</div><div>            return to_return</div><div>        return wrapper</div><div><br></div></div><div>    #for method_name, method in inspect.getmembers(cairo.Context, predicate=inspect.ismethod):</div>


<div>    for method_name, method in inspect.getmembers(cairo.Context):</div><div>        if not method_name.startswith(&#39;__&#39;):</div><div><div>            setattr(cls, method_name, return_self_decorator(method))</div>

<div>
    return cls</div></div></div><div><br></div><div>Pretty sure this accomplishes what you wanted :).</div><div><br></div><div>cheers,</div><div>David</div><div><div><div><br><div class="gmail_quote">On Thu, Jun 14, 2012 at 11:56 PM, David Ginsburg <span dir="ltr">&lt;<a href="mailto:dav9dg@gmail.com" target="_blank">dav9dg@gmail.com</a>&gt;</span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>Hello,</div>The problem with this is if a method needs to return a value other than self, you break it.<div>
<div>This is probably hacky, but you could accomplish what you want doing the following:</div><div><br></div></div><div>
<div>import inspect</div><div>import functools</div><div><br></div><div>def make_chainable_context(cls):</div><div><br></div><div>    def return_self_decorator(func):</div><div>        </div><div>        def wrapper(self, *args, **kwargs):</div>



<div>            to_return = func(self, *args, **kwargs)</div><div>            if to_return is None:</div><div>                to_return = self</div><div>            return to_return</div><div>        return wrapper</div>



<div><br></div><div>    for method_name, method in inspect.getmembers(cairo.Context, predicate=inspect.ismethod):</div><div>        setattr(cls, method_name, return_self_decorator(method))</div><div>    return cls</div><div>



            </div><div><br></div><div>@make_chainable_context</div><div>class ChainableContext(cairo.Context):</div><div>    pass</div></div><div><br></div><div>This way methods that return something other than None are not broken.</div>



<div><br></div><div>cheers,</div><div>David</div><div><br><div class="gmail_quote"><div><div>On Thu, Jun 14, 2012 at 11:28 PM, Brian Palmer <span dir="ltr">&lt;<a href="mailto:bpalmer@gmail.com" target="_blank">bpalmer@gmail.com</a>&gt;</span> wrote:<br>



</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div><div>On Thu, Jun 14, 2012 at 10:52 PM, Ian Zimmerman <span dir="ltr">&lt;<a href="mailto:itz@buug.org" target="_blank">itz@buug.org</a>&gt;</span> wrote:<br>



</div><div class="gmail_quote"><div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Isaac&gt; Hi, Why do you need each of the methods to return the instance?<br>
Isaac&gt; Can you just wrap the method calls in a function and return the<br>
Isaac&gt; instance?<br>
<br>
I am not married to the idea of a wrapper class, but I don&#39;t understand<br>
what you propose instead.  What would the example code look like under<br>
your scheme?<br></blockquote></div><div><br>Your initial solution seems like it&#39;d work:<br>class Wrap(object):<br>  def __init__(self, ctx):<br>    self.ctx = ctx<br><br>  def __getattr__(self, name):<br>    def myf(*args, **kwargs):<br>




      getattr(self.ctx, name)(*args, **kwargs)<br>      return self<br>    return myf<br><br>There are benefits to being less dynamic, but this might be good enough.<br></div></div>
<br></div></div><div>_______________________________________________<br>
Baypiggies mailing list<br>
<a href="mailto:Baypiggies@python.org" target="_blank">Baypiggies@python.org</a><br>
To change your subscription options or unsubscribe:<br>
<a href="http://mail.python.org/mailman/listinfo/baypiggies" target="_blank">http://mail.python.org/mailman/listinfo/baypiggies</a><br></div></blockquote></div><br></div>
</blockquote></div><br></div></div></div></div>
</blockquote></div><br></div></div></div>
</blockquote></div><br>