[Twisted-Python] A Python metaclass for Twisted allowing __init__ to return a Deferred

Terry Jones terry at jon.es
Sun Nov 2 19:16:50 EST 2008


Hi JP

> I usually solve this kind of problem like this:
> 
>     d = aFuncReturningADeferred()
>     d.addCallback(MyClass)
>     d.addCallback(cb)

See? I knew there'd be a 3-line solution somewhere :-)

That's very cute, I'd never have thought of that...  Python is so nice.

My (weak?) response is that your solution isn't quite so general. What if I
want __init__ to generate the deferred based on its args, or on the result
of other functions called based on its args? Yes, I can do all that work
before using your lovely d.addCallback(MyClass), but then the logic of what
the class does is starting to leak out into the code that should be calling
the class. And you can't encapsulate THAT code into another class, because
its __init__ would in turn have to return a deferred.

BTW, I sometimes have the feeling that Deferreds are like how M$
characterizes the GPL. Viral. Once you call anything creating a Deferred,
you're hooked - whatcha gonna do with that Deferred boy? Take one sip of
the Deferred Kool Aid and the next thing you know you're on a drip.

> I'll not try to claim anything about the level of elegance, though. :)

History will smile on you JP.

> For less surprisiness, I'd suggest that you at least restrict the result
> of the Deferred returned from __init__ to firing with None or self and
> make the argument to the first callback on the Deferred returned by
> MyClass() just be the new instance.

Hmmm. OK. I think you're right. The caller has no business knowing what the
Deferred returned in any case. And if the class itself wants the result it
can add a callback and stick it on self.  That's good, I had been hoping to
return just the instance, but then it occurred to me to send back the
result too.

BTW, I started out trying to think of a way to just say

  x = MyClass(...)

and have that result in the instance. But the only ways I could think of
doing that were disgusting and broken (e.g., make a *function* called
MyClass and use inlineCallbacks and some other class the metaclass would
build). So the __instantiate__ call seemed like a big win, even though I
don't like it much either.

Thanks!

Terry




More information about the Twisted-Python mailing list