[Trimming...] On Thu, Jan 2, 2014 at 2:49 AM, Tobias Oberstein <[email protected]> wrote:
> Interesting analogy. Yes, seems language/syntax parsing a file is similar to > protocol parsing a wire-level stream transport. I wonder about the "sending > leg": with language parsers, this would be probably the AST. With network > protocols, it's more of producing a 2nd stream conforming again to the same > "syntax": for sending to the other peer. But reading and writing are almost always asymmetrical. E.g. for HTTP I wouldn't see how you could reuse the push code for the input side (say, the part that parses the headers) to write the response. The process is just very different. > I am wondering what happens if you take timing constraints into account. Eg. > with WebSocket, for DoS protection, one might want to have the initial > opening handshake finished in <N seconds. Hence you want to check after N > seconds if state "HANDSHAKE_FINISHED" has been reached. A > > yield from socket.read_handshake() > > (simplified) will however just "block" infinitely. So I need a 2nd coroutine > for the timeout. And the timeout will need to check .. an instance variable > for state. Or can I have a timing out yield from? You'd write this yield from asyncio.wait_for(socket.read_handshake(), <timeout_in_seconds>) The implementation uses a Future instead of a coroutine. When the timeout happens, the yield-from will raise asyncio.TimeoutError and asyncio.CancelledError will be thrown into the read_handshake coroutine (and perhaps deeper, into whatever is *actually* blocking at this precise point). > How would you do a pull-style UI toolkit? Transforming each push-style > callback for UI widgets into pull-style code > > yield from button1.onclick() > # handle button1 click > > or > > evt = yield from ui.onevent() > if evt.target == "button1" and evt.type == "click": > # handle button1 click > > The latter leads to one massive, monolithic code block handling all UI > interaction. The former leads to many small "sequential" looking code pieces > .. similar to callbacks. And those "distributed" code pieces somehow need to > interact with each other. I honestly haven't figured this one out. It seems all popular UI frameworks use push style. I recall hearing about a system called NeWS (http://en.wikipedia.org/wiki/NeWS) that IIRC used a pull-style APIs for a mouse-based UI. This was in the '80s, before the necessary abstractions were widely agreed on. E.g. the mouse-tracking logic for drawing a shape or selecting objects was done using a loop that blocked until the mouse button was released. I don't think it was very successful though. > FWIW, the - for me - most comfortable and managable way of doing UI is via > "reactive programming", e.g. in JavaScript http://knockoutjs.com/ > > Eg. say some "x" is changing asynchronously (like a UI input field widget) > and some "y" needs to be changed _whenever_ "x" changes (like a UI label). > > In reactive programming, I can basically write code > > y = f(x) > > and the reactive engine will _analyze_ that code, and hook up push-style > callback code under the hood, so that _whenever_ x changes, f() is > _automatically_ reapplied. This idea has been around the block a few times too. Some of my former colleagues on the ABC project (Python's predecessor) went on to do something like that, and eventually their research morphed into XForms (http://en.wikipedia.org/wiki/XForms). More recently the Elm programming language (http://elm-lang.org/) also uses this paradigm. I'd say it's worth knowing about and nice when it's what you need, but, like Haskell, limited by the non-pure nature of many practical problems. > In fact, Twisted endpoints are so cool (sorry for mentioning this here), I > can also run WebSocket over any stream transport, like Unix domain sockets, > pipes, serial: > > https://github.com/tavendo/AutobahnPython/tree/master/examples/twisted/websocket/echo_endpoints I'm not entirely sure what Twisted endpoints are and why they're so cool. (Glyph kept telling me they were cool but not quite ready or something, so I never had a good look.) But most of what you describe here should be possible equally well with asyncio's protocol/transport abstractions (which are pretty close to those in Twisted, if you aren't too attached to Deferred). So what's missing?(Probably nothing that couldn't be added on top of asyncio as a 3rd party package.) > The thing is: the abstracted WebSocket semantics of "reliable, ordered > datagram" neither fit TCP nor UDP. True, but that doesn't mean it doesn't fit the datagram transport/protocol APIs -- there's nothing in their definition that says the underlying transport can't be reliable and ordered. :-) > It does fit SCTP: > > http://en.wikipedia.org/wiki/Stream_Control_Transmission_Protocol > > SCTP is available natively > > http://www.freebsd.org/cgi/man.cgi?query=sctp&sektion=4 > > in which case you need to use new kernel API (Posix sockets don't have it) > and it can be layered over UDP, which is used eg with the upcoming WebRTC > HTML5 standard: > > http://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-06 I'm not sure that the actual implementation is relevant here -- following Twisted's example, asyncio's transports and protocols don't require a specific underlying internet protocol. (E.g. the common stream protocol has TCP and TLS implementations, and shares a lot of APIs with pipes (named or unnamed). > So I think it really could be worth to define an abstract interface in > asyncio with the appropiate semantics for transports to implement. And > implementing transports then could be WebSocket and SCTP or even > shared-memory message queues .. A concrete question: what APIs are missing in asyncio's datagram transport and protocol classes to support SCTP and WebSocket? (Apart from the constructor -- but the constructor is explicitly not part of the transport/protocol abstraction, just like the __init__ signature is not part of most ABCs.) > Happy new year, Same to you and anyone else who read this far! -- --Guido van Rossum (python.org/~guido)
