Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Errback api #363
What do you think of this, as an idea?
I'm not sure about the "_create_future()" API, and perhaps an interface would be nice for "the thing we give to errbacks" (i.e. Failure or AsyncioFailure).
I'm hopeful there's a better way to get asyncio to do an event-loop iteration, or call all completed Futures or whatever. But for now at least all the error-case tests can run in both asyncio and Twisted.
@meejah Thanks for splitting this out into a separate PR! I have been thinking about this. Please be prepared for more discussions;) You might wonder why I'm so reluctant and not merge such a relatively straight-forward PR right away .. I will try to explain why.
What we do actually do here is come up with a mixin that allows one to write idiomatic code that runs on both Twisted and asyncio: source code compatibility.
The uniform handling of failures (and hence the need for a asyncio analog to Twisted's
Further, the current classes in AutobahnPython are somewhat misplaced/misdesigned for the general task above anyway:
As this could be of use not only in AutobahnPython, I have created: https://github.com/tavendo/txaio
AutobahnPython currently only depends on six. With above, the 2nd dependency would be txaio.
So the task would be: write txaio and adjust the AutobahnPython code to using that. What do you think? Makes sense?
No worries, I understand why you want to get this right.
In the end, for Twisted, it provides really nice default logging if we can call
I'll have to look into tulip/asyncio some more to get a better handle how this sort of thing is "normally" done in callbacks.
The other piece (that I basically just hacked in "something" in this PR) is the testing aspect. I can't find any information about the/"a" recommended way to "wait" for your Future in a test (i.e. like returning a Defered to
What might be worthwhile -- perhaps as part of
p.s. in the meantime, do you think it's worth making a (somewhat smaller) PR that at least fixes the things that definitely won't work in protocol.py + asyncio? I think there's only two:
...but I guess also,
Additionally, instead of a mixin-style class (requiring inheritence, even though they're all static methods), what about just having
So client code (e.g. in Autobahn) would end up looking something like:
import txaio d = txaio.create_future() ... txaio.resolve_future(d, "yay") class Something(object): def do_a_thing(self): return txaio.create_future_success("it worked")
...etc. This would allow users of txaio decide whether they wanted to use inheritence or composition or bare methods or whatever to accomplish their task. What do you think?
@meejah Ah, I like it. Only exposing simple functions in txaio, and let users choose.
I think users should be able to actively select Twisted vs asyncio, even when both are available.
from txaio import tx as txaio
from txaio import aio as txaio
or something like it.
We still would use these functions then in AutobahnPython to create a (private) mixin class?
Since the reason the current code looks like it does is because I was looking for a solution with the following.
Essentially, the code there should run on both Twisted and asyncio. The concrete classes for
The user then imports the concrete class
from autobahn.wamp.twisted import ApplicationSession from autobahn.wamp.asyncio import ApplicationSession
Or is there a different solution?
We could use
Users would "select" asyncio/trollius/twisted by installing them. As in: if you have Twisted, you use it; else try asyncio; else try trollius; else fail.
So far the only hard part is trying to support the nice options Twisted has for "DeferredList" and gather. I might split this API so its simpler code, and more-explicit/easier to understand from the user level.
Here are the requirements that come to mind:
I currently don't see how we can achieve above without mixin classes - but I am open to other ideas.
If we do not find another solution (other than mixins), those event loop mixin classes should reside in
In other words, the USP of
I think it should be possible to let the entry point into Autobahn (ApplicationRunner if I recall correctly) to choose the underlying framework based on the passed reactor/eventloop (if its a reacton -> twisted, if its an eventloop -> asyncio). Classes which then need framework-independent functionality could be implemented by using dependency injection (which the entry point sets up). As Autobahn already is heavily build around IoC, dependency injection would fit pretty well into it IMHO.
We could realize dependency injection by utilizing constructors or by directly modifying the object instance (
The only non-mixin solution I can think of would be this:
from txaio import tx as _txaio class ApplicationSession(...): txaio = _txaio
...and then protocol.py code looks like
from txaio.tx import LoopMixin class ApplicationSession(LoopMixin, ...):
I have a "working" PoC in my fork of
There's one change from what I copied out of Autobahn: we weren't supporting
Here's how the above looks, as an idea.
is now based off the simplified