curio v0.6 Release Notes
Release Date: 2017-02-15 // about 7 years ago-
02/13/2017 Added a withfd=True option to UniversalQueue. For example:
q = UniversalQueue(withfd=True) If added, the queue internally sets up an I/O loopback where putting items on the queue write bytes to an I/O channel. The queue then spouts a fileno() method and becomes pollable in other event loops. This is potentially useful strategy for integrating Curio with GUIs and other kinds of foreign event loops.
02/11/2017 Added a guard for proper use of asynchronous generators involving asynchronous finalization. Must be wrapped by finalize(). For example:
async def some_generator(): ... try: yield val finally: await action() async def coro(): ... async with finalize(some_generator()) as agen: async for item in agen: ... Failure to do this results in a RuntimeError if an asynchronous generator is iterated. This is not needed for generators that don't perform finalization steps involving async code.
02/08/2017 New Kernel.run() method implementation. It should be backwards compatible, but there are two new ways of using it:
kernel = Kernel() ... # Run a coroutine with a timeout/deadline applied to it try: result = kernel.run(coro, timeout=secs) except TaskTimeout: print('Timed out') # Run all daemonic tasks through a single scheduling cycle # with no blocking kernel.run() # Run all daemonic tasks through a cycle, but specify a # timeout on internal blocking kernel.run(timeout=secs)
02/06/2017 New aside() function for launching a Curio task in an independent process. For example:
async def child(name, n): print('Hello from', name) for i in range(n): print('name says', i) await sleep(1) async def main(): t = await aside(child, 'Spam', 10) # Runs in subprocess await t.join() run(main()) In a nutshell, aside(coro, *args, **kwargs) creates a clean Python interpreter and invokes curio.run(coro(*args, **kwargs)) on the supplied coroutine. The return value of aside() is a Task object. Joining with it returns the child exit code (normally 0). Cancelling it causes a TaskCancelled exception to be raised in the child. aside() does not involve a process fork or pipe. There is no underlying communication between the child and parent process. If you want communication, use a Channel object or set up some other kind of networking.
02/06/2017 Some improvements to message passing and launching tasks in subprocesses. A new Channel object makes it easy to establish message passing between two different interpreters. For example, here is a producer program:
# producer.py from curio import Channel, run async def producer(ch): while True: c = await ch.accept(authkey=b'peekaboo') for i in range(10): await c.send(i) await c.send(None) # Sentinel if __name__ == '__main__': ch = Channel(('localhost', 30000)) run(producer(ch)) Here is a consumer program:: # consumer.py from curio import Channel, run async def consumer(ch): c = await ch.connect(authkey=b'peekaboo') while True: msg = await c.recv() if msg is None: break print('Got:', msg) if __name__ == '__main__': ch = Channel(('localhost', 30000)) run(consumer(ch)) A Channel is a lot like a socket except that it sends discrete messages. Any picklable Python compatible object can be passed.
🛠 02/03/2017 Fixed a few regressions in SSL sockets and the Kernel.run() method.