{ "info": { "author": "Michael Elsdorfer", "author_email": "michael@elsdorfer.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Internet :: WWW/HTTP" ], "description": "# trio-protocol\n\nThis implements the `asyncio.Transport` interface and foundational asyncio classes such as `asyncio.Task` on top of [`trio`](https://github.com/python-trio/trio), to aid porting `asyncio` libraries. The idea is to allow `trio` to run an [`asyncio.Protocol`](https://docs.python.org/3/library/asyncio-protocol.html#protocols), making it possible for a single code base to run on both frameworks.\n\nIt is **not a goal** of `trio-protocol` to let you run `asyncio` code on `trio` without any changes. If you need this, look at [`asyncio-trio`](https://github.com/python-trio/trio-asyncio).\n\n\n#### What is and is not currently supported\n\nThis is an early version. You can use it to support some basic `asyncio` servers. However, it lacks:\n\n- Support for clients (only servers have been tested)\n- A test suite.\n- Robust experience running it in production.\n- Likely, implementations for useful/necessary methods that asyncio code is using in the wild, and should be added.\n\n\n## Usage\n\nLet's say you want to run the [`asyncio-len-prefixed-string-protocol.py` from the python3-samples repository](https://github.com/eliben/python3-samples/blob/master/async/asyncio-len-prefixed-string-protocol.py) on top of `trio`. \n\nIf you follow the link, you see that the module first implements subclass of `asyncio.Protocol`, which it then subclasses further. Ultimately, the protocol as implemented reads strings from the client, prefixed by length, and sends back an `\"ok\"` message.\n\nAt the bottom of the file, you'll find the following code to start the server:\n\n```python\nloop = asyncio.get_event_loop()\ncoro = loop.create_server(MyStringReceiver, '127.0.0.1', 5566)\nserver = loop.run_until_complete(coro)\nprint('serving on {}'.format(server.sockets[0].getsockname()))\n\ntry:\n loop.run_forever()\nexcept KeyboardInterrupt:\n print(\"exit\")\nfinally:\n server.close()\n loop.close()\n```\n\nThis creates an `asyncio` server running on port `5566`. Every connection to that port will be served by the `MyStringReceiver` protocol. Specifically, `loop.create_server()` will setup the server's socket (since it is an `async` function, it will not do anything until awaited, which in this case we do via `loop.run_until_complete`). Whenever someone connects to the server, asyncio will schedule a task to handle the connection. We run `loop.run_forever()` to have the loop be active and process these tasks.\n\nNow let's run this on `trio` instead. Replace this section of the code with:\n\n```python\nimport trio\nfrom trio_protocol import run_server\n\ntrio.run(run_server, MyStringReceiver, '127.0.0.1', 5566)\n```\n\nAnd that would work! The code is a bit shorter than the original, partly because setting up trio is just less verbose, and partly because we do less: We do not handle `KeyboardInterrupt` cleanly, and we do not print a message once we are ready to accept connections. Instead, `trio_protocol.run_server` is a shortcut that does everything for us: It opens a nursery, starts a server, and runs the `asyncio.Protocol` on that server.\n\nIf we want to copy the original code more exactly, I can do this:\n\n```python\nimport trio\nfrom trio_protocol import create_server\n\nasync def run_server():\n async with trio.open_nursery() as nursery:\n server = await create_server(nursery, MyStringReceiver, '127.0.0.1', 5566)\n print('serving on {}'.format(server.sockets[0].getsockname()))\n\ntry:\n trio.run(run_server)\nexcept KeyboardInterrupt:\n print(\"exit\")\n```\n\n```trio_protocol.create_server``` will start listening on the socket. It will return a `trio_protocol.Server` object that is intended to mirror `asyncio.Server`. You are then free to run your own code, with the server running in the background, similar to the `asyncio` version.\n\n>>> Note: To test this server, you can use:\n>>> `python -c \"import struct; print((b'%shello world' % struct.pack('