{ "info": { "author": "Jonathan Martin", "author_email": "therouquinblanc@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "# A simple asyncio wrapper attempting to look like Trio\n\n[![Build Status](https://travis-ci.org/RouquinBlanc/traio.svg?branch=master)](https://travis-ci.org/RouquinBlanc/traio) [![Coverage Status](https://coveralls.io/repos/github/RouquinBlanc/traio/badge.svg?branch=master)](https://coveralls.io/github/RouquinBlanc/traio?branch=master)\n\nWhen going deeper and deeper with asyncio, and managing a lot of tasks\nin parallel, you notice that on top of having a lot to deal with\nto keep an eye on all your task, you also end up always doing the\nsame kind of boiler plate, and the code can become easily twisted and\nunreadable.\n\n[Trio](https://github.com/python-trio/trio) is there to make asynchronous\nprogramming easy and more \"for humans\".\n\nTraio (as kind of Trio on top of Asyncio) let you use asyncio with a little of\nthe philosophy of Trio, mostly the Nursery concept (called Scope here).\nIt also synthesize the most common pattern we are using for handling async\ntasks in a sane way.\n\n## Disclaimer\n\nThis is *not* a replacement for Trio: if you do a full Trio-like project,\njust use Trio! It's just truly awesome, but in some cases you get stuck \nwith asyncio, but still want to have a code you can read and manage...\n\nBecause we run on top of asyncio, we are quite limited in how we can handle\ncancellation, scopes, and coroutines. This is *just* on top of asyncio, this\nis not an alternative! But on the good side, you can mix this with regular\nasyncio code, which can look appealing.\n\n## Examples\n\n### Simple Scope\n\nThe main way to use the Scope is (like in Trio) as a context manager\n\n```python\nimport asyncio\nfrom traio import Scope\n\nasync def fetch_url(x):\n # Do something long\n await asyncio.sleep(3)\n\nasync def main():\n async with Scope(timeout=10) as scope:\n for i in range(10):\n scope.spawn(fetch_url(i))\n```\n\nThe `Scope.spawn` method, called on an awaitable thing, will spawn a task and\nregister it on the scope. An equivalent exist using the `<<` operator (see next\nexample).\n\nWhen reaching the end of the context block, the code will block until:\n- all tasks are done\n- or the timeout is over\n- or the scope get's cancelled.\n\nYou can also use the Scope without context manager:\n\n```python\nimport asyncio\nfrom traio import Scope\n\nasync def fetch_url(x):\n # Do something long\n await asyncio.sleep(3)\n\nasync def main():\n # Equivalent to previous example\n scope = Scope(timeout=10)\n\n for i in range(10):\n scope << fetch_url(i)\n\n scope.finalize()\n await scope\n```\n\nAwaiting a scope will block until the scope is fully complete: all active tasks\nhave finished or the scope was cancelled. But unless `scope.finalize()` is called,\na scope will note stop on the last task being complete, only on cancellation.\n\nThe `finalize` method is called automatically when used as a context manager.\n\n### Names and logger\n\nIf you went deep enough in asyncio mysteries, you know that tracing code is\n(for now) kind of a nightmare... For that reason, Scope as well as tasks can\nbe instantiated with a name. The Scope can also take a logger which will be\nused for tracing most of the calls and task life cycle, mostly with debug level. \n\n### Special tasks\n\n`Scope.spawn` can be called with different parameters with interesting\neffects:\n\n- The `bubble` boolean parameter controls task error bubbling. A task will\nbubble by default. This means that an error in the task will cause the task \nto stop (of course), but the scope will be cancelled as well and raise \nthe given error. This is the default behavior.\nBut it can be useful in some cases not to do that, and just ignore a task.\nNot that if you await manually a task, or add a done callback, this cancels\nbubbling automatically: if you take the pain of waiting for a task,\nit's not to get all the rest cancelled!\n\n```python\nimport asyncio\nfrom traio import Scope\n\nasync def fetch_url():\n # Do something long\n await asyncio.sleep(10)\n\nasync def trivial():\n await asyncio.sleep(0.01)\n raise ValueError('not interesting')\n\nasync def main():\n\n async with Scope(timeout=0.5) as n:\n # This will try to run for 10 seconds\n n << fetch_url()\n\n # This will run a bit then raise (but not 'bubble')\n n.spawn(trivial(), bubble=False)\n\n # Eventually after 0.5 seconds the Scope times out and\n # gives a TImeoutError\n```\n\n- A task can be marked as `master`, in that case the scope will die with the \ntask when done. This is typically useful when you have one main task to be\nperformed and other background ones, which have no meaning if the main one stops.\n\n```python\nimport asyncio\nfrom traio import Scope\n\nasync def fetch_url():\n # Do something long\n await asyncio.sleep(10)\n\nasync def trivial():\n await asyncio.sleep(0.01)\n\nasync def main():\n\n async with Scope(timeout=0.5) as n:\n # This will try to run for 10 seconds\n n << fetch_url()\n\n # This will run a bit then scope gets cancelled when it ends\n n.spawn(trivial(), master=True)\n```\n\n- A task by default is `awaited`, which means the scope will wait\nfor it to finish during finalisation stage, before exiting.\nIt is possible to mark some tasks as not `awaited` if you want a task running,\nbut not so essential that it should prevent cancellation. \nTypically, a background job which has no meaning alone.\n\n```python\nimport asyncio\nfrom traio import Scope\n\nasync def background():\n while True:\n # Do something periodic and sleep\n await asyncio.sleep(1)\n\nasync def job():\n # Do the real work\n await asyncio.sleep(10)\n\nasync def main():\n\n async with Scope() as n:\n # Spawn a background job\n n.spawn(background(), awaited=False)\n\n # Do what you have to do.\n n << job()\n\n # At this point, job is done and background task was cancelled\n```\n\nNote you can combine all flags; If bubble is False and master is True,\nthe scope will exit silently when the task is done, even with an exception,\nfor example.\n\n### Nested Scope\n\nThat's one of the most exciting ones: you can spawn a sub-scope from the\noriginal one, which will follow the same rules as any Scope but will as well\ndie if the parent is cancelled!\n\n```python\nimport asyncio\nfrom traio import Scope\n\nasync def fetch_url():\n # Do something long\n await asyncio.sleep(10)\n\nasync def main():\n\n async with Scope(timeout=0.2) as parent:\n async with parent.fork(timeout=0.5) as inner:\n # This will try to run for 10 seconds\n inner << fetch_url()\n\n # Here the outer Scope will timeout first and will cancel the inner one!\n```\n\n### Running synchronous code with executors\n\nIt is possible to run synchronous code from a scope using the\n`loop.run_in_executor` method; this would return a coroutine which\nyou can spawn as usual. But beware of using that method! The same way\ninterrupts handling is a mess in asyncio, using thread from asyncio is tricky.\nMost OS don't support cancelling running threads, so does Python.\nAs such, once your executor code is running, the scope has no way to\nactually stop it; if you cancel the scope, the corresponding future will be\ncancelled but the task will continue running if not yet finished, resulting in\nvarious \"fun\" situations if that task has side effects...\n\nSo: yes, you can use this, but at your own risks!\n\n```python\nimport asyncio\nimport time\nfrom traio import Scope\n\ndef fetch_url():\n # Do something long, sync!\n time.sleep(10)\n\nasync def main():\n async with Scope(timeout=0.2) as scope:\n scope << asyncio.get_event_loop().run_in_executor(None, fetch_url)\n```\n\n### Getting current Scope\n\nUsing the awesome [contextvars](https://www.python.org/dev/peps/pep-0567/) and \nthe current backport of it [aiocontextvars](https://github.com/fantix/aiocontextvars),\nwe can keep track of the current active scope without necessarily passing the\nscope variable all along the call chain.\n\n```python\nasync def handler(client):\n # This runs in the scope `main_scope`\n # Create a subscope of the current one\n async with Scope.get_current().fork() as s:\n # Here we are in the scope of `s`, as well as spawned tasks\n s << do_something(client)\n s << do_something_else(client)\n\nasync def server(main_scope):\n # This runs in the scope `main_scope`\n client = await new_connection()\n main_scope.spawn(handler(client))\n\nasync def main():\n async with Scope() as main_scope:\n main_scope << server(main_scope)\n main_scope << do_something_else()\n```\n\n## Status\n\nThis is beta. We are not going to change the API (much) anymore.\n\n## TODOS\n\n- write more examples\n- extend the API:\n - new kinds of tasks to investigate, for example executors (although we have no way to stop \n a thread executor...)\n- play more with the real Trio and get a better feeling of it\n- get some user feedback if possible!\n\n## Similar projects\n\nYou may like as well [Ayo](https://github.com/Tygs/ayo), discovered in parallel of writting this lib!\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/RouquinBlanc/traio/", "keywords": "asyncio,nursery,trio,even loop", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "traio", "package_url": "https://pypi.org/project/traio/", "platform": "", "project_url": "https://pypi.org/project/traio/", "project_urls": { "Homepage": "https://github.com/RouquinBlanc/traio/" }, "release_url": "https://pypi.org/project/traio/0.5.2/", "requires_dist": [ "aiocontextvars (~=0.2)", "typing; python_version < \"3.6\"" ], "requires_python": "", "summary": "A simple asyncio wrapper attempting to look like Trio", "version": "0.5.2" }, "last_serial": 4497195, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "5c19e72da92def0945b4b3e937af966b", "sha256": "8c6f88215c7aac9f47e24346c773906fde9a227d040dba41853f5284fa9f8c9b" }, "downloads": -1, "filename": "traio-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "5c19e72da92def0945b4b3e937af966b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8224, "upload_time": "2018-11-05T12:02:53", "url": "https://files.pythonhosted.org/packages/6f/f7/23bccb3131240d7c2a91702de5d9bdf1a5d13fd5771c277c1a3be3fd8e0f/traio-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "638a41ca3cc7a94c7165adf594cf9ee9", "sha256": "04f7412cfa097f06c3d15edb5aed27f2376b7c259dc7e0f577185b93c6d07ebf" }, "downloads": -1, "filename": "traio-0.1.0.tar.gz", "has_sig": false, "md5_digest": "638a41ca3cc7a94c7165adf594cf9ee9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6036, "upload_time": "2018-11-05T12:02:54", "url": "https://files.pythonhosted.org/packages/2a/2a/d4ae108285f5e40d04e38e3c2b7e4e446dacf762ca298eeb8d3263c2a7d9/traio-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "d4bdad86073bca329720ee99df1f3be6", "sha256": "9973903145a6612193be0eedbe79da737f51312f4dae660630dcc814bd284cff" }, "downloads": -1, "filename": "traio-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "d4bdad86073bca329720ee99df1f3be6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12081, "upload_time": "2018-11-06T10:36:34", "url": "https://files.pythonhosted.org/packages/41/04/d6ae355695f626476b22bbd21fde1cd93f72a6d9bb4082c5cbd1621ba460/traio-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "14e9428a0b43bb3f56b0b47aca0953f0", "sha256": "5068390d8690c1afce1b1215c42a107700f12b1e59468064310927a9ad011a68" }, "downloads": -1, "filename": "traio-0.1.1.tar.gz", "has_sig": false, "md5_digest": "14e9428a0b43bb3f56b0b47aca0953f0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6859, "upload_time": "2018-11-06T10:36:35", "url": "https://files.pythonhosted.org/packages/d7/80/fb25a88165c8c718ca10082247a3fc97e836920cb2fb8ccc6c25d2bc07be/traio-0.1.1.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "6faa9d2a7c06a45e89d930797fe91581", "sha256": "b200a761ce88badd6e5178675a02a4b8ebcb7abb6dc4e14c528609b8a3f914ca" }, "downloads": -1, "filename": "traio-0.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "6faa9d2a7c06a45e89d930797fe91581", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13150, "upload_time": "2018-11-07T12:09:39", "url": "https://files.pythonhosted.org/packages/6d/aa/9946b3ff86f82dd22cf77490bfb0ddf7c1200e903fc248fb1124ae9a1e3e/traio-0.2.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7eb49dfde0a1a556e10da5f6e62dfa55", "sha256": "f4a8d4511d2ae85fa4c3677541fd029d9bedcb3d1023636e46f68db86b41ea5c" }, "downloads": -1, "filename": "traio-0.2.0.tar.gz", "has_sig": false, "md5_digest": "7eb49dfde0a1a556e10da5f6e62dfa55", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7483, "upload_time": "2018-11-07T12:09:40", "url": "https://files.pythonhosted.org/packages/d9/fa/1886e2aa082da1a078effd1613434fafc118e8421e54e5aecbd425c2801f/traio-0.2.0.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "0b546f99d0bf673e5a4dcad7434cc7c8", "sha256": "97cad822e807f79945cc5f8ad4e8f53552610d96b54cf084628074991112b8c0" }, "downloads": -1, "filename": "traio-0.3.1-py3-none-any.whl", "has_sig": false, "md5_digest": "0b546f99d0bf673e5a4dcad7434cc7c8", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 15305, "upload_time": "2018-11-10T20:43:30", "url": "https://files.pythonhosted.org/packages/a8/dc/c4884eb06da2cd3065db52722303bec973c4d208fa601668edbb370c8171/traio-0.3.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4fb555a73f920228cedb9166d31f0ae4", "sha256": "f19a645e0090439f91fc4c263dc927d7ed462408b1aa1ca2018337f4f47037a2" }, "downloads": -1, "filename": "traio-0.3.1.tar.gz", "has_sig": false, "md5_digest": "4fb555a73f920228cedb9166d31f0ae4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13193, "upload_time": "2018-11-10T20:43:33", "url": "https://files.pythonhosted.org/packages/fc/9d/f0d061100cdab703d65b1b81e0516af0645988a800482c3188302eb87a8b/traio-0.3.1.tar.gz" } ], "0.3b0": [ { "comment_text": "", "digests": { "md5": "ad9500b2aecb1d989badf4240c1a9bd9", "sha256": "6f9204ccf550668f14b7c5f4cf13d8856a29059f8ae4d736355bc13bb4a6a540" }, "downloads": -1, "filename": "traio-0.3b0-py3-none-any.whl", "has_sig": false, "md5_digest": "ad9500b2aecb1d989badf4240c1a9bd9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 14518, "upload_time": "2018-11-07T23:30:49", "url": "https://files.pythonhosted.org/packages/12/73/4b94c8b8e4d17f522c1709fe45ffb3f1955fdc8168837f3b9b93f0df2d46/traio-0.3b0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5b42e295674c1c4566b9747bc2659d40", "sha256": "dddf8b327b94e1ede34f2f2bbd72f2ba1414c726d59cf500815e8ac20a150fc8" }, "downloads": -1, "filename": "traio-0.3b0.tar.gz", "has_sig": false, "md5_digest": "5b42e295674c1c4566b9747bc2659d40", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12379, "upload_time": "2018-11-07T23:30:51", "url": "https://files.pythonhosted.org/packages/18/56/b1c34f005dcb6db753bc4cf3149bc52b9bf647034cf98cc4f50d15a33d89/traio-0.3b0.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "ccb23078e6df4a8c52d309d866611f0b", "sha256": "2d4c2fc2a3ca81f74b713848ebce863972fc2da4f1609e2a79c9e505408a88ba" }, "downloads": -1, "filename": "traio-0.4.0-py3-none-any.whl", "has_sig": false, "md5_digest": "ccb23078e6df4a8c52d309d866611f0b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 19949, "upload_time": "2018-11-10T20:43:31", "url": "https://files.pythonhosted.org/packages/a4/47/85b97b9f9ebeae95f11a7d11baf66b69acccfbc1215c5d34539f4a119cdc/traio-0.4.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5b4f99bb1d996925f29029005c7b96e4", "sha256": "3856f56eef68ae329df45b0cc5fb5a01dd7c063f8946d2d41f3e6d0c5cccf00d" }, "downloads": -1, "filename": "traio-0.4.0.tar.gz", "has_sig": false, "md5_digest": "5b4f99bb1d996925f29029005c7b96e4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14557, "upload_time": "2018-11-10T20:43:34", "url": "https://files.pythonhosted.org/packages/c3/fd/99292e0c670f929e1e43a417fc82f7003dec706241535c8dc2f8e3e2db79/traio-0.4.0.tar.gz" } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "446b197c077b6eae3324503a90414e49", "sha256": "48cc839f1040da39ea6cc8e1c417fe901d2e6f345093be2a5f3015668d87450a" }, "downloads": -1, "filename": "traio-0.4.1-py3-none-any.whl", "has_sig": false, "md5_digest": "446b197c077b6eae3324503a90414e49", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 20066, "upload_time": "2018-11-12T19:26:13", "url": "https://files.pythonhosted.org/packages/eb/72/a37eff5d73804b508ad553f097ce85053ecb7927823b5fe8335baf3ca04f/traio-0.4.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7137afa1750783e7c556a97057381bee", "sha256": "7403ff243ceaedbb76c705798a9cc704abc002aef0fa35048906452aed6db825" }, "downloads": -1, "filename": "traio-0.4.1.tar.gz", "has_sig": false, "md5_digest": "7137afa1750783e7c556a97057381bee", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14270, "upload_time": "2018-11-12T19:26:14", "url": "https://files.pythonhosted.org/packages/3c/e2/2f93bb066eaf18e852396499c326295a39487851d42378ad7a34e8cc4e31/traio-0.4.1.tar.gz" } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "d947d35716270034c946bd20e1ef2ba9", "sha256": "0fcb236588c11ba38ce5fc5ef7929503111b15a03441a31026162c626b21e2f1" }, "downloads": -1, "filename": "traio-0.5.0-py3-none-any.whl", "has_sig": false, "md5_digest": "d947d35716270034c946bd20e1ef2ba9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 17724, "upload_time": "2018-11-15T08:12:04", "url": "https://files.pythonhosted.org/packages/51/f0/31e7f963fb3d7784c49653167df4877db97a8aeec5d6b242a9aee1675c80/traio-0.5.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9532585faea62df2e101293b98403a56", "sha256": "cc7e923fe6a3e09ef39d25f3d6f22e631968a6b4cd2a87bc1348073b6694b160" }, "downloads": -1, "filename": "traio-0.5.0.tar.gz", "has_sig": false, "md5_digest": "9532585faea62df2e101293b98403a56", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15089, "upload_time": "2018-11-15T08:12:05", "url": "https://files.pythonhosted.org/packages/c9/b8/5214889a24370b67ac22b1960cb811e000abc176c6d825892abe9e462282/traio-0.5.0.tar.gz" } ], "0.5.1": [ { "comment_text": "", "digests": { "md5": "eef34cbde94e52f610e1cfefd7189aed", "sha256": "f78ee2d3455a8655efaa922ca91ec17db7b0341930692e2e74ebf316a981d004" }, "downloads": -1, "filename": "traio-0.5.1-py3-none-any.whl", "has_sig": false, "md5_digest": "eef34cbde94e52f610e1cfefd7189aed", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 18740, "upload_time": "2018-11-16T10:03:24", "url": "https://files.pythonhosted.org/packages/f2/80/c21454db9311c852bdf3f245fb539c888996d33fcf7d41b1ea9f86f0ac4d/traio-0.5.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ffdb0b59f5f3985a02248a2573050fb4", "sha256": "f626e2d4ce18ba25b6af3d67fa9b2579796c2d5429966f4585edfd95f3c7303d" }, "downloads": -1, "filename": "traio-0.5.1.tar.gz", "has_sig": false, "md5_digest": "ffdb0b59f5f3985a02248a2573050fb4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16257, "upload_time": "2018-11-16T10:03:25", "url": "https://files.pythonhosted.org/packages/06/54/17be4affdfaccd6b23e9fcb35464a83d606edd998d28955934068fed487c/traio-0.5.1.tar.gz" } ], "0.5.2": [ { "comment_text": "", "digests": { "md5": "571e94a3038d4dc1aa428a6273eb5477", "sha256": "18a3e922dd79d8db6ca05d6fcc65ac93302cf112e0fb1a20f286410098643bcc" }, "downloads": -1, "filename": "traio-0.5.2-py3-none-any.whl", "has_sig": false, "md5_digest": "571e94a3038d4dc1aa428a6273eb5477", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23830, "upload_time": "2018-11-17T13:50:49", "url": "https://files.pythonhosted.org/packages/a6/0a/7f96af06f6e6e98ff32e315a9ff61acaf8421a6b9bec10a76d15bb322b7a/traio-0.5.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "47e2f05eeb32f083f4acb7ccc2a00b21", "sha256": "94fd719b462933f1b6bae6407d76df2bf3f00da6b6c44af6c28f5e938f55ee4e" }, "downloads": -1, "filename": "traio-0.5.2.tar.gz", "has_sig": false, "md5_digest": "47e2f05eeb32f083f4acb7ccc2a00b21", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18279, "upload_time": "2018-11-17T13:50:50", "url": "https://files.pythonhosted.org/packages/61/5f/058dbb289a6859430b9407fa7fce1557d1752fc1b0db14a3a61ec0188a27/traio-0.5.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "571e94a3038d4dc1aa428a6273eb5477", "sha256": "18a3e922dd79d8db6ca05d6fcc65ac93302cf112e0fb1a20f286410098643bcc" }, "downloads": -1, "filename": "traio-0.5.2-py3-none-any.whl", "has_sig": false, "md5_digest": "571e94a3038d4dc1aa428a6273eb5477", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23830, "upload_time": "2018-11-17T13:50:49", "url": "https://files.pythonhosted.org/packages/a6/0a/7f96af06f6e6e98ff32e315a9ff61acaf8421a6b9bec10a76d15bb322b7a/traio-0.5.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "47e2f05eeb32f083f4acb7ccc2a00b21", "sha256": "94fd719b462933f1b6bae6407d76df2bf3f00da6b6c44af6c28f5e938f55ee4e" }, "downloads": -1, "filename": "traio-0.5.2.tar.gz", "has_sig": false, "md5_digest": "47e2f05eeb32f083f4acb7ccc2a00b21", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18279, "upload_time": "2018-11-17T13:50:50", "url": "https://files.pythonhosted.org/packages/61/5f/058dbb289a6859430b9407fa7fce1557d1752fc1b0db14a3a61ec0188a27/traio-0.5.2.tar.gz" } ] }