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's my ugly workaround:</div><div><br></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> #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('__'):</div><div> setattr(cls, method_name, return_self_decorator(method))</div><div>
return cls</div></div><div><br></div><div>Pretty sure this accomplishes what you wanted :).</div><div><br></div><div>cheers,</div><div>David</div><div><br><div class="gmail_quote">On Thu, Jun 14, 2012 at 11:56 PM, David Ginsburg <span dir="ltr"><<a href="mailto:dav9dg@gmail.com" target="_blank">dav9dg@gmail.com</a>></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 class="im">
<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 class="h5">On Thu, Jun 14, 2012 at 11:28 PM, Brian Palmer <span dir="ltr"><<a href="mailto:bpalmer@gmail.com" target="_blank">bpalmer@gmail.com</a>></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 class="h5"><div>On Thu, Jun 14, 2012 at 10:52 PM, Ian Zimmerman <span dir="ltr"><<a href="mailto:itz@buug.org" target="_blank">itz@buug.org</a>></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> Hi, Why do you need each of the methods to return the instance?<br>
Isaac> Can you just wrap the method calls in a function and return the<br>
Isaac> instance?<br>
<br>
I am not married to the idea of a wrapper class, but I don'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'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 class="im">_______________________________________________<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>