CINXE.COM
Issue 24017: Implemenation of the PEP 492 - Coroutines with async and await syntax - Python tracker
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title> Issue 24017: Implemenation of the PEP 492 - Coroutines with async and await syntax - Python tracker </title> <link rel="shortcut icon" href="@@file/favicon.ico" /> <link rel="stylesheet" type="text/css" href="@@file/main.css" /> <link rel="stylesheet" type="text/css" href="@@file/style.css" /> <link rel="search" type="application/opensearchdescription+xml" href="@@file/osd.xml" title="Python bug tracker search" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script nonce="4d81bfcc06fe5189d5a90d53fef6f1c5a212483c2d498049d5a5e4fffeb67e1f" type="text/javascript"> submitted = false; function submit_once() { if (submitted) { alert("Your request is being processed.\nPlease be patient."); return false; } submitted = true; return true; } function help_window(helpurl, width, height) { HelpWin = window.open('https://bugs.python.org/' + helpurl, 'RoundupHelpWindow', 'scrollbars=yes,resizable=yes,toolbar=no,height='+height+',width='+width); HelpWin.focus () } </script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/jquery-ui.js"></script> <script type="text/javascript" src="@@file/issue.item.js"></script> <link rel="stylesheet" type="text/css" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/smoothness/jquery-ui.css" /> </head> <body> <!-- Logo --> <h1 id="logoheader"> <a accesskey="1" href="." id="logolink"> <img src="@@file/python-logo.gif" alt="homepage" border="0" id="logo" /></a> </h1> <div id="utility-menu"> <!-- Search Box --> <div id="searchbox"> <form name="searchform" method="get" action="issue" id="searchform"> <div id="search"> <input type="hidden" name="@columns" value="id,github,activity,title,creator,assignee,status,type" /> <input type="hidden" name="@sort" value="-activity" /> <input type="hidden" name="@filter" value="status" /> <input type="hidden" name="@action" value="searchid" /> <input type="hidden" name="ignore" value="file:content" /> <input class="input-text" id="search-text" name="@search_text" size="10" /> <input type="submit" id="submit" value="search" name="submit" class="input-button" /> <input type="radio" name="status" id="status_notresolved" value="-1,1,3" /> <label for="status_notresolved">open</label> <input type="radio" name="status" checked="checked" id="status_all" value="-1,1,2,3" /> <label for="status_all">all</label> </div> </form> </div> </div> <div id="left-hand-navigation"> <!-- Main Menu NEED LEVEL TWO HEADER AND FOOTER --> <div id="menu"> <ul class="level-one"> <li><a href="https://www.python.org/" title="Go to the Python homepage">Python Home</a></li> <li><a href="https://www.python.org/about/" title="About The Python Language">About</a></li> <li><a href="https://www.python.org/blogs/" title="">News</a></li> <li><a href="https://www.python.org/doc/" title="">Documentation</a></li> <li><a href="https://www.python.org/downloads/" title="">Downloads</a></li> <li><a href="https://www.python.org/community/" title="">Community</a></li> <li><a href="https://www.python.org/psf/" title="Python Software Foundation">Foundation</a></li> <li><a href="https://devguide.python.org/" title="Python Developer's Guide">Developer's Guide</a></li> <li class="selected"><a href="." class="selected" title="Python Issue Tracker">Issue Tracker</a> <ul class="level-two"> <li> <strong>Issues</strong> <ul class="level-three"> <li><a href="issue?@template=search&status=1">Search</a></li> <li><a href="issue?@action=random">Random Issue</a></li> <li> <form method="post" action="issue24017"> <input type="submit" class="form-small" value="Show issue:" /> <input class="form-small" size="4" type="text" name="@number" /> <input type="hidden" name="@type" value="issue" /> <input type="hidden" name="@action" value="show" /> </form> </li> </ul> </li> <li> <strong>Summaries</strong> <ul class="level-three"> <li> <a href="issue?status=1&@sort=-activity&@columns=id%2Cgithub%2Cactivity%2Ctitle%2Ccreator%2Cstatus&@dispname=Issues%20with%20patch&@startwith=0&@group=priority&keywords=2&@action=search&@filter=&@pagesize=50">Issues with patch</a> </li> <li> <a href="issue?status=1&@sort=-activity&@columns=id%2Cgithub%2Cactivity%2Ctitle%2Ccreator%2Cstatus&@dispname=Easy%20issues&@startwith=0&@group=priority&keywords=6&@action=search&@filter=&@pagesize=50">Easy issues</a> </li> <li> <a href="issue?@template=stats">Stats</a> </li> </ul> </li> <li> <strong>User</strong> <form method="post" action="issue24017"> <ul class="level-three"> <li> Login<br /> <input size="10" name="openid_identifier" style="" /><br /> <input size="10" type="password" name="__login_password" /><br /> <input type="hidden" name="@action" value="Login" /> <input type="checkbox" name="remember" id="remember" /> <label for="remember">Remember me?</label><br /> <input class="form-small" type="submit" value="Login" /><br /> <input type="hidden" name="__came_from" value="https://bugs.python.org/issue24017?"> <input type="hidden" name="@sort" value=""/> <input type="hidden" name="@group" value=""/> <input type="hidden" name="@pagesize" value="50"/> <input type="hidden" name="@startwith" value="0"/> </li> <li> </li> <li><a href="user?@template=forgotten">Lost your login?</a></li> </ul> </form> </li> <li> <strong>Administration</strong> <ul class="level-three"> <li> <a href="user?@sort=username">User List</a></li> <li> <a href="user?iscommitter=1&@action=search&@sort=username&@pagesize=300">Committer List</a></li> </ul> </li> <li> <strong>Help</strong> <ul class="level-three"> <li><a href="http://docs.python.org/devguide/triaging.html"> Tracker Documentation</a></li> <li><a href="http://wiki.python.org/moin/TrackerDevelopment"> Tracker Development</a></li> <li><a href="https://github.com/python/psf-infra-meta/issues"> Report Tracker Problem</a></li> </ul> </li> </ul> </li> </ul> </div> <!-- menu --> </div> <!-- left-hand-navigation --> <div id="content-body"> <div id="body-main"> <div id="content"> <div id="breadcrumb"> Issue24017 </div> <div id="migration-notice"> <div id="migration-images"> <img width="32" src="@@file/python-logo-small.png" /> ➜ <a href="https://github.com/python/cpython/issues"><img width="32" src="@@file/gh-icon.png" /></a> </div> <p>This issue tracker <b>has been migrated to <a href="https://github.com/python/cpython/issues">GitHub</a></b>, and is currently <b>read-only</b>.<br /> For more information, <a title="GitHub FAQs" href="https://devguide.python.org/gh-faq/"> see the GitHub FAQs in the Python's Developer Guide.</a></p> </div> <div> <form method="post" name="itemSynopsis" onsubmit="return submit_once()" enctype="multipart/form-data" action="issue24017"> <div id="gh-issue-link"> <a href="https://github.com/python/cpython/issues/68205"> <img width="32" src="@@file/gh-icon.png" /> <p> <span>This issue has been migrated to GitHub:</span> https://github.com/python/cpython/issues/68205 </p> </a> </div> <fieldset><legend>classification</legend> <table class="form"> <tr> <th class="required"><a href="http://docs.python.org/devguide/triaging.html#title" target="_blank">Title</a>:</th> <td colspan="3"> <span>Implemenation of the PEP 492 - Coroutines with async and await syntax</span> <input type="hidden" name="title" value="Implemenation of the PEP 492 - Coroutines with async and await syntax"> </td> </tr> <tr> <th class="required"><a href="http://docs.python.org/devguide/triaging.html#type" target="_blank">Type</a>:</th> <td>enhancement</td> <th><a href="http://docs.python.org/devguide/triaging.html#stage" target="_blank">Stage</a>:</th> <td>resolved</td> </tr> <tr> <th><a href="http://docs.python.org/devguide/triaging.html#components" target="_blank">Components</a>:</th> <td>Interpreter Core</td> <th><a href="http://docs.python.org/devguide/triaging.html#versions" target="_blank">Versions</a>:</th> <td>Python 3.5</td> </tr> </table> </fieldset> <fieldset><legend>process</legend> <table class="form"> <tr> <th><a href="http://docs.python.org/devguide/triaging.html#status" target="_blank">Status</a>:</th> <td>closed</td> <th><a href="http://docs.python.org/devguide/triaging.html#resolution" target="_blank">Resolution</a>:</th> <td>fixed</td> </tr> <tr> <th> <a href="http://docs.python.org/devguide/triaging.html#dependencies" target="_blank">Dependencies</a>: </th> <td> <a href="issue2292" class="closed" title="Missing *-unpacking generalizations">2292</a> <a href="issue22906" class="closed" title="PEP 479: Change StopIteration handling inside generators">22906</a> <a href="issue24018" class="closed" title="add a Generator ABC">24018</a> <a href="issue24180" class="closed" title="PEP 492: Documentation">24180</a> <a href="issue24184" class="closed" title="PEP 492: Add AsyncIterator and AsyncIterable to collections.abc">24184</a> <a href="issue24315" class="closed" title="collections.abc: Coroutine should be derived from Awaitable">24315</a> <a href="issue24316" class="closed" title="Fix types.coroutine to accept objects from Cython">24316</a> <a href="issue24400" class="closed" title="Awaitable ABC incompatible with functools.singledispatch">24400</a> </td> <th><a href="http://docs.python.org/devguide/triaging.html#superseder" target="_blank">Superseder</a>:</th> <td> </td> </tr> <tr> <th> <a href="http://docs.python.org/devguide/triaging.html#assigned-to" target="_blank">Assigned To</a>: </th> <td> yselivanov </td> <th> <a href="http://docs.python.org/devguide/triaging.html#nosy-list" target="_blank">Nosy List</a><!-- <span tal:condition="context/nosy_count" tal:replace="python: ' (%d)' % context.nosy_count" /> -->: </th> <td> alex.gronholm, asvetlov, gvanrossum, larry, ncoghlan, python-dev, scoder, vstinner, yselivanov </td> </tr> <tr> <th> <a href="http://docs.python.org/devguide/triaging.html#priority" target="_blank">Priority</a>: </th> <td>release blocker</td> <th> <a href="http://docs.python.org/devguide/triaging.html#keywords" target="_blank">Keywords</a>: </th> <td>patch</td> </tr> </table> </fieldset> </form> <p>Created on <strong>2015-04-20 19:33</strong> by <strong>vstinner</strong>, last changed <strong>2022-04-11 14:58</strong> by <strong>admin</strong>. This issue is now <strong style="color:#00F; background-color:inherit;">closed</strong>.</p> <table class="files"> <tr><th colspan="5" class="header">Files</th></tr> <tr> <th>File name</th> <th>Uploaded</th> <th>Description</th> <th>Edit</th> </tr> <tr> <td> <a href="file39148/await_01.patch">await_01.patch</a> </td> <td> <span>yselivanov</span>, <span>2015-04-20 19:55</span> </td> <td></td> <td> <a href="/review/24017/#ps14685">review</a> </td> </tr> <tr> <td> <a href="file39155/await_02.patch">await_02.patch</a> </td> <td> <span>yselivanov</span>, <span>2015-04-21 03:59</span> </td> <td></td> <td> <a href="/review/24017/#ps14690">review</a> </td> </tr> <tr> <td> <a href="file39314/await_03.patch">await_03.patch</a> </td> <td> <span>yselivanov</span>, <span>2015-05-07 20:13</span> </td> <td></td> <td> <a href="/review/24017/#ps14798">review</a> </td> </tr> <tr> <td> <a href="file39325/await_04.patch">await_04.patch</a> </td> <td> <span>yselivanov</span>, <span>2015-05-08 21:15</span> </td> <td></td> <td> <a href="/review/24017/#ps14807">review</a> </td> </tr> <tr> <td> <a href="file39337/await_05.patch">await_05.patch</a> </td> <td> <span>yselivanov</span>, <span>2015-05-11 01:32</span> </td> <td></td> <td> <a href="/review/24017/#ps14812">review</a> </td> </tr> <tr> <td> <a href="file39344/await_06.patch">await_06.patch</a> </td> <td> <span>yselivanov</span>, <span>2015-05-11 19:59</span> </td> <td></td> <td> <a href="/review/24017/#ps14816">review</a> </td> </tr> <tr> <td> <a href="file39354/with.patch">with.patch</a> </td> <td> <span>yselivanov</span>, <span>2015-05-13 03:36</span> </td> <td></td> <td> <a href="/review/24017/#ps14826">review</a> </td> </tr> </table> <table class="messages"> <tr><th colspan="4" class="header">Messages (69)</th></tr> <tr> <th> <a href="#msg241678" id="msg241678">msg241678</a> - <a href="msg241678">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-04-20 19:45</th> </tr> <tr> <td colspan="4" class="content"> <pre>Here's the first patch (git diff master..await). Should be easier to review and work from there.</pre> </td> </tr> <tr> <th> <a href="#msg241679" id="msg241679">msg241679</a> - <a href="msg241679">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-04-20 19:55</th> </tr> <tr> <td colspan="4" class="content"> <pre>Attaching a patch generated with mercurial</pre> </td> </tr> <tr> <th> <a href="#msg241687" id="msg241687">msg241687</a> - <a href="msg241687">(view)</a></th> <th>Author: STINNER Victor (vstinner) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-04-20 21:43</th> </tr> <tr> <td colspan="4" class="content"> <pre>Does the implementation depends on the implementation of the <a href="https://www.python.org/dev/peps/pep-0479/">PEP 479</a>? (issue <a class="closed" title="[closed] PEP 479: Change StopIteration handling inside generators" href="issue22906">#22906</a>) > Attaching a patch generated with mercurial Next time, if possible, try to skip generated files. Maybe write a script for that, but sorry I don't know how :-(</pre> </td> </tr> <tr> <th> <a href="#msg241697" id="msg241697">msg241697</a> - <a href="msg241697">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-04-21 03:59</th> </tr> <tr> <td colspan="4" class="content"> <pre>Attaching a revised patch (all Victor's comments but asyncio changes)</pre> </td> </tr> <tr> <th> <a href="#msg242056" id="msg242056">msg242056</a> - <a href="msg242056">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-04-26 15:11</th> </tr> <tr> <td colspan="4" class="content"> <pre>Could we have type slots for the new special methods? Otherwise, implementing the protocol in C would be fairly inefficient, especially for async iteration. I'm asking because Cython's generator type is not Python's generator type, but implementing the rest of the proposed protocol doesn't seem to be all that difficult.</pre> </td> </tr> <tr> <th> <a href="#msg242064" id="msg242064">msg242064</a> - <a href="msg242064">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-04-26 17:27</th> </tr> <tr> <td colspan="4" class="content"> <pre>> Could we have type slots for the new special methods? Otherwise, implementing the protocol in C would be fairly inefficient, especially for async iteration. I don't think it's necessary to have slots for __aiter__, __anext__, __aenter__ and __aexit__. Async iteration will never be as fast as regular iteration, and there is plenty overhead in it. And we don't need slots for async context managers as we don't have slots for regular ones. What might be a good idea is to add a slot for __await__ method -- tp_await. This will allow to implement Futures in C efficiently. I'd rename 'tp_reserved' for this purpose. Victor, your thoughts?</pre> </td> </tr> <tr> <th> <a href="#msg242086" id="msg242086">msg242086</a> - <a href="msg242086">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-04-26 23:27</th> </tr> <tr> <td colspan="4" class="content"> <pre>In fact I will likely add tp_await in the next PEP iteration. I need it to implement another feature.</pre> </td> </tr> <tr> <th> <a href="#msg242304" id="msg242304">msg242304</a> - <a href="msg242304">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-01 12:19</th> </tr> <tr> <td colspan="4" class="content"> <pre>> I don't think it's necessary to have slots for __aiter__, __anext__, __aenter__ and __aexit__. Async iteration will never be as fast as regular iteration, and there is plenty overhead in it. You seem to be assuming that the outer loop is the asyncio I/O loop. That might not be the case. It might be a thread-pool executor, it might be an in-memory task switcher, or it might just be something passing on items from a list. At least "__anext__" is worth being fast, IMHO. Also note that one advantage of slots is that the user can cache their value to keep calling the same C function multiple times. That is not the case for a Python method, which can easily be replaced. Some iterators do that with their __next__ method, and it's perfectly valid. Having to look up the Python method on each iteration and calling through it sounds like unnecessary overhead.</pre> </td> </tr> <tr> <th> <a href="#msg242326" id="msg242326">msg242326</a> - <a href="msg242326">(view)</a></th> <th>Author: Guido van Rossum (gvanrossum) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-01 15:18</th> </tr> <tr> <td colspan="4" class="content"> <pre>I think we can continue this discussion *after* the PEP's been accepted.</pre> </td> </tr> <tr> <th> <a href="#msg242627" id="msg242627">msg242627</a> - <a href="msg242627">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-06 00:16</th> </tr> <tr> <td colspan="4" class="content"> <pre>I'll upload the most recent patch soon.</pre> </td> </tr> <tr> <th> <a href="#msg242731" id="msg242731">msg242731</a> - <a href="msg242731">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-07 20:13</th> </tr> <tr> <td colspan="4" class="content"> <pre>Third patch attached. Victor, it would be great if you can review it!</pre> </td> </tr> <tr> <th> <a href="#msg242779" id="msg242779">msg242779</a> - <a href="msg242779">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-08 21:15</th> </tr> <tr> <td colspan="4" class="content"> <pre>Another iteration: - support of new syntax in lib2to3 - collections.abc.Awaitable</pre> </td> </tr> <tr> <th> <a href="#msg242793" id="msg242793">msg242793</a> - <a href="msg242793">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-09 03:29</th> </tr> <tr> <td colspan="4" class="content"> <pre>We also need a Coroutine ABC. Both the "GeneratorType" and "CO_COROUTINE" checks are too restrictive. Also see <a class="closed" title="[closed] add a Generator ABC" href="issue24018">issue 24018</a>, which this one should in fact depend on.</pre> </td> </tr> <tr> <th> <a href="#msg242848" id="msg242848">msg242848</a> - <a href="msg242848">(view)</a></th> <th>Author: Alyssa Coghlan (ncoghlan) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-10 03:34</th> </tr> <tr> <td colspan="4" class="content"> <pre>Review sent - very nice work on this Yury. Highlights: * I concur with Stefan that we should have a full PyCoroutineMethods struct at the C level, with a "tp_as_coroutine" pointer to that replacing the current tp_reserved slot * I also concur with Stefan about adding a Coroutine ABC * PyType_FromSpec (and typeslots.h) will need updating once we agree on a slot structure (with my recommendation being "define C level slots for all of the new <a href="https://www.python.org/dev/peps/pep-0492/">PEP 492</a> methods") * I found CO_COROUTINE/CO_NATIVE_COROUTINE confusing as a reader of the implementation, as they only told me how the objects were defined, rather than telling me why I should care. Based on what I gleaned of their intended purpose from reading the implementation, I suggest switching this to instead use CO_COROUTINE (set for all coroutines, regardless of how they were defined) and CO_ITERABLE_COROUTINE (set only for those coroutines that also support iteration), and adjusting the naming of other APIs accordingly. * I found the names of the WITH_CLEANUP_ENTER and WITH_CLEANUP_EXIT bytecodes misleading, as they don't refer to the corresponding context management phases - they're both related to the "exit" phase. WITH_CLEANUP_START and WITH_CLEANUP_FINISH should be clearer for readers (both of the implementation and of the disassembled bytecode).</pre> </td> </tr> <tr> <th> <a href="#msg242860" id="msg242860">msg242860</a> - <a href="msg242860">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-10 16:21</th> </tr> <tr> <td colspan="4" class="content"> <pre>> Review sent - very nice work on this Yury. Thanks a lot, Nick! Highlights: > * I concur with Stefan that we should have a full PyCoroutineMethods struct at the C level, with a "tp_as_coroutine" pointer to that replacing the current tp_reserved slot Do you think that tp_as_async is a better name? (I explained my point of view in code review comments) Also, do we need slots for __aenter__ and __aexit__? We don't have slots for regular context manager protocol, fwiw. > * I also concur with Stefan about adding a Coroutine ABC I will. We definitely need it. > * PyType_FromSpec (and typeslots.h) will need updating once we agree on a slot structure (with my recommendation being "define C level slots for all of the new <a href="https://www.python.org/dev/peps/pep-0492/">PEP 492</a> methods") > * I found CO_COROUTINE/CO_NATIVE_COROUTINE confusing as a reader of the implementation, as they only told me how the objects were defined, rather than telling me why I should care. Based on what I gleaned of their intended purpose from reading the implementation, I suggest switching this to instead use CO_COROUTINE (set for all coroutines, regardless of how they were defined) and CO_ITERABLE_COROUTINE (set only for those coroutines that also support iteration), and adjusting the naming of other APIs accordingly. I agree that CO_COROUTINE is something that we should use for 'async def' functions (instead of CO_NATIVE_COROUTINE). However, CO_ITERABLE_COROUTINE sounds a bit odd to me, as generator-based coroutines (at least in asyncio) aren't supposed to be iterated over. How about CO_GENBASED_COROUTINE flag? > * I found the names of the WITH_CLEANUP_ENTER and WITH_CLEANUP_EXIT bytecodes misleading, as they don't refer to the corresponding context management phases - they're both related to the "exit" phase. WITH_CLEANUP_START and WITH_CLEANUP_FINISH should be clearer for readers (both of the implementation and of the disassembled bytecode). Big +1. Your names are much better.</pre> </td> </tr> <tr> <th> <a href="#msg242862" id="msg242862">msg242862</a> - <a href="msg242862">(view)</a></th> <th>Author: Andrew Svetlov (asvetlov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-10 17:40</th> </tr> <tr> <td colspan="4" class="content"> <pre>On Sun, May 10, 2015 at 7:21 PM, Yury Selivanov <<a href="mailto:report@bugs.python.org">report@bugs.python.org</a>> wrote: > > Yury Selivanov added the comment: > >> Review sent - very nice work on this Yury. > > Thanks a lot, Nick! > > Highlights: > >> * I concur with Stefan that we should have a full PyCoroutineMethods struct at the C level, with a "tp_as_coroutine" pointer to that replacing the current tp_reserved slot > > Do you think that tp_as_async is a better name? (I explained my point of view in code review comments) > > Also, do we need slots for __aenter__ and __aexit__? We don't have slots for regular context manager protocol, fwiw. > >> * I also concur with Stefan about adding a Coroutine ABC > > I will. We definitely need it. > >> * PyType_FromSpec (and typeslots.h) will need updating once we agree on a slot structure (with my recommendation being "define C level slots for all of the new <a href="https://www.python.org/dev/peps/pep-0492/">PEP 492</a> methods") > >> * I found CO_COROUTINE/CO_NATIVE_COROUTINE confusing as a reader of the implementation, as they only told me how the objects were defined, rather than telling me why I should care. Based on what I gleaned of their intended purpose from reading the implementation, I suggest switching this to instead use CO_COROUTINE (set for all coroutines, regardless of how they were defined) and CO_ITERABLE_COROUTINE (set only for those coroutines that also support iteration), and adjusting the naming of other APIs accordingly. > > I agree that CO_COROUTINE is something that we should use for 'async def' functions (instead of CO_NATIVE_COROUTINE). However, CO_ITERABLE_COROUTINE sounds a bit odd to me, as generator-based coroutines (at least in asyncio) aren't supposed to be iterated over. How about CO_GENBASED_COROUTINE flag? > Maybe CO_ASYNC_COROUTINE and CO_OLDSTYLE_COROUTINE? This is wild proposal, feel free to ignore it. > >> * I found the names of the WITH_CLEANUP_ENTER and WITH_CLEANUP_EXIT bytecodes misleading, as they don't refer to the corresponding context management phases - they're both related to the "exit" phase. WITH_CLEANUP_START and WITH_CLEANUP_FINISH should be clearer for readers (both of the implementation and of the disassembled bytecode). > > Big +1. Your names are much better. > > ---------- > > _______________________________________ > Python tracker <<a href="mailto:report@bugs.python.org">report@bugs.python.org</a>> > <<a href="http://bugs.python.org/issue24017">http://bugs.python.org/issue24017</a>> > _______________________________________</pre> </td> </tr> <tr> <th> <a href="#msg242877" id="msg242877">msg242877</a> - <a href="msg242877">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-11 01:32</th> </tr> <tr> <td colspan="4" class="content"> <pre>New patch is attached. Nick, I think that all of your feedback should be addressed in this patch. Major changes: 1. There are two code flags now: CO_COROUTINE and CO_GENBASED_COROUTINE (I'm OK to use another name, see my older comments). CO_COROUTINE is assigned to all 'async def' code objects. CO_GENBASED_COROUTINE is assigned to generator-based coroutines decorated with types.coroutine(). 2. tp_await renamed to tp_as_async. (I'm OK to use another name, please see my older comment first) PyAsyncMethods struct holds three slots: am_await, am_aiter, am_anext. Implementing am_exit would be tricky, because of how SETUP_WITH opcode is engineered. I'd really prefer to not to add it. 3. collections.abc.Coroutine. 4. etc (all other feedback from you).</pre> </td> </tr> <tr> <th> <a href="#msg242912" id="msg242912">msg242912</a> - <a href="msg242912">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-11 19:59</th> </tr> <tr> <td colspan="4" class="content"> <pre>Nick, Guido, Updated patch attached.</pre> </td> </tr> <tr> <th> <a href="#msg242927" id="msg242927">msg242927</a> - <a href="msg242927">(view)</a></th> <th>Author: Alyssa Coghlan (ncoghlan) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-12 00:03</th> </tr> <tr> <td colspan="4" class="content"> <pre>Latest version looks good to me (aside from a quibble about whether StopAsyncIteration should inherit from BaseException instead of Exception - see my review for details). Based on Guido's explanation in the review, I also suggested adding the following example method to the PEP as part of the rationale for StopAsyncIteration: def __anext__(self): try: data = await self._get_data() except EOFError: raise StopAsyncIteration return data The trick is that when __anext__ is itself a coroutine, we really do have 3 exit paths: * suspension to wait for events (await) * returning the next value (return) * terminating iteration (raise StopAsyncIteration)</pre> </td> </tr> <tr> <th> <a href="#msg242928" id="msg242928">msg242928</a> - <a href="msg242928">(view)</a></th> <th>Author: Alyssa Coghlan (ncoghlan) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-12 00:16</th> </tr> <tr> <td colspan="4" class="content"> <pre>Guido convinced me that having StopAsyncIteration inherit from Exception was the right approach, as it means errors are more likely to be of the "we caught it when we shouldn't have" variety, rather than the harder to debug "an exception escaped when it shouldn't have" variety. This isn't like SystemExit, KeyboardInterrupt or GeneratorExit where they're specifically designed to reliably terminate a thread of execution. That means I can offer an unreserved +1 on the current patch (#6) for beta 1 :)</pre> </td> </tr> <tr> <th> <a href="#msg242931" id="msg242931">msg242931</a> - <a href="msg242931">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-05-12 02:31</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/957478e95b26">957478e95b26</a> by Yury Selivanov in branch '3.4': asyncio: Support <a href="https://www.python.org/dev/peps/pep-0492/">PEP 492</a>. Issue <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">#24017</a>. <a href="https://hg.python.org/cpython/rev/957478e95b26">https://hg.python.org/cpython/rev/957478e95b26</a> New changeset <a href="https://hg.python.org/lookup/44c1db190525">44c1db190525</a> by Yury Selivanov in branch 'default': asyncio: Merge 3.4 -- Support <a href="https://www.python.org/dev/peps/pep-0492/">PEP 492</a>. Issue <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">#24017</a>. <a href="https://hg.python.org/cpython/rev/44c1db190525">https://hg.python.org/cpython/rev/44c1db190525</a></pre> </td> </tr> <tr> <th> <a href="#msg242935" id="msg242935">msg242935</a> - <a href="msg242935">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-05-12 03:03</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/eeeb666a5365">eeeb666a5365</a> by Yury Selivanov in branch 'default': <a href="https://www.python.org/dev/peps/pep-0492/">PEP 0492</a> -- Coroutines with async and await syntax. Issue <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">#24017</a>. <a href="https://hg.python.org/cpython/rev/eeeb666a5365">https://hg.python.org/cpython/rev/eeeb666a5365</a></pre> </td> </tr> <tr> <th> <a href="#msg242936" id="msg242936">msg242936</a> - <a href="msg242936">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-12 03:06</th> </tr> <tr> <td colspan="4" class="content"> <pre>Guido, Nick, Victor, Thanks for your reviews and guidance! The patch has been committed to the default branch.</pre> </td> </tr> <tr> <th> <a href="#msg242937" id="msg242937">msg242937</a> - <a href="msg242937">(view)</a></th> <th>Author: Guido van Rossum (gvanrossum) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-12 03:23</th> </tr> <tr> <td colspan="4" class="content"> <pre>Thank you Yury! You are a coding machine. On Mon, May 11, 2015 at 8:06 PM, Yury Selivanov <<a href="mailto:report@bugs.python.org">report@bugs.python.org</a>> wrote: > > Yury Selivanov added the comment: > > Guido, Nick, Victor, > Thanks for your reviews and guidance! The patch has been committed to the > default branch. > > ---------- > > _______________________________________ > Python tracker <<a href="mailto:report@bugs.python.org">report@bugs.python.org</a>> > <<a href="http://bugs.python.org/issue24017">http://bugs.python.org/issue24017</a>> > _______________________________________ ></pre> </td> </tr> <tr> <th> <a href="#msg242938" id="msg242938">msg242938</a> - <a href="msg242938">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-05-12 04:06</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/3a3cc2b9a1b2">3a3cc2b9a1b2</a> by Yury Selivanov in branch 'default': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: Update NEWS file. <a href="https://hg.python.org/cpython/rev/3a3cc2b9a1b2">https://hg.python.org/cpython/rev/3a3cc2b9a1b2</a></pre> </td> </tr> <tr> <th> <a href="#msg242979" id="msg242979">msg242979</a> - <a href="msg242979">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-05-12 15:30</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/0dc3b61f1dfa">0dc3b61f1dfa</a> by Yury Selivanov in branch 'default': Issue <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">#24017</a>: Plug ref leak. <a href="https://hg.python.org/cpython/rev/0dc3b61f1dfa">https://hg.python.org/cpython/rev/0dc3b61f1dfa</a></pre> </td> </tr> <tr> <th> <a href="#msg242982" id="msg242982">msg242982</a> - <a href="msg242982">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-05-12 15:46</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/ee7d2c9c70ab">ee7d2c9c70ab</a> by Yury Selivanov in branch '3.4': asyncio: Make sure sys.set_coroutine_wrapper is called *only* when loop is running. <a href="https://hg.python.org/cpython/rev/ee7d2c9c70ab">https://hg.python.org/cpython/rev/ee7d2c9c70ab</a> New changeset <a href="https://hg.python.org/lookup/874edaa34b54">874edaa34b54</a> by Yury Selivanov in branch 'default': asyncio: Make sure sys.set_coroutine_wrapper is called *only* when loop is running. <a href="https://hg.python.org/cpython/rev/874edaa34b54">https://hg.python.org/cpython/rev/874edaa34b54</a></pre> </td> </tr> <tr> <th> <a href="#msg242984" id="msg242984">msg242984</a> - <a href="msg242984">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-05-12 18:28</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/9d2c4d887c19">9d2c4d887c19</a> by Yury Selivanov in branch 'default': Issue <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">#24017</a>: Unset asyncio event loop after test. <a href="https://hg.python.org/cpython/rev/9d2c4d887c19">https://hg.python.org/cpython/rev/9d2c4d887c19</a></pre> </td> </tr> <tr> <th> <a href="#msg243031" id="msg243031">msg243031</a> - <a href="msg243031">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-13 03:36</th> </tr> <tr> <td colspan="4" class="content"> <pre>Nick, Guido, Attached is a patch that fixes a refleak in 'async with' implementation. The problem is related to WITH_CLEANUP_START/WITH_CLEANUP_FINISH opcodes. For regular 'with' statements, these opcodes go one after another (essentially, it was one opcode before 'async with'). For 'async with' statements, we have a GET_AWAITABLE/YIELD_FROM pair between them. Now, if an error occurred during running a GET_AWAITABLE or a YIELD_FROM opcode, WITH_CLEANUP_FINISH was unreachable. All blocks were correctly unwound by the eval loop, but exception object got too many DECREFS. My solution is to continue using WITH_CLEANUP_START/WITH_CLEANUP_FINISH opcodes, but use SETUP_EXCEPT to guard them and nested YIELD_FROM and GET_AWAITABLE. In case of an exception, I propose to use another new opcode -- ASYNC_WITH_CLEANUP_EXCEPT. It unwinds the block set up by SETUP_EXCEPT, restores exception, NULLifies a copy of exception in the stack and does 'goto error', letting eval loop do the rest. "./python.exe -m test -R3:3 test_coroutines" with this patch reports no refleaks. I also updates test_coroutines with a lot of new 'async with' tests, I think that I got all usecases covered. Please take a look at the patch, I want to commit it as soon as possible.</pre> </td> </tr> <tr> <th> <a href="#msg243033" id="msg243033">msg243033</a> - <a href="msg243033">(view)</a></th> <th>Author: Alyssa Coghlan (ncoghlan) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-13 05:00</th> </tr> <tr> <td colspan="4" class="content"> <pre>I'm bothered by the remarkable proliferation of new opcodes for the <a href="https://www.python.org/dev/peps/pep-0492/">PEP 492</a> handling. Is there are a specific reason this implicit exception handler can't be decomposed and implemented using the same opcodes as are used to implement explicit exception handlers?</pre> </td> </tr> <tr> <th> <a href="#msg243035" id="msg243035">msg243035</a> - <a href="msg243035">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-13 05:10</th> </tr> <tr> <td colspan="4" class="content"> <pre>> Is there are a specific reason this implicit exception handler can't be decomposed and implemented using the same opcodes as are used to implement explicit exception handlers? I don't think it's possible to replace ASYNC_WITH_CLEANUP_EXCEPT opcode with some combination of existing opcodes. What might be possible is to implement 'async with' without using WITH_CLEANUP_* opcodes at all. Let me try that.</pre> </td> </tr> <tr> <th> <a href="#msg243036" id="msg243036">msg243036</a> - <a href="msg243036">(view)</a></th> <th>Author: Alyssa Coghlan (ncoghlan) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-13 05:15</th> </tr> <tr> <td colspan="4" class="content"> <pre>I'm going to dig into this one locally, as it sounds to me like something may be going wrong with the refcounts in the complex stack manipulation involved in WITH_CLEANUP. It seems plausible that there's a genuinely missing incref/decref pair somewhere in the non-exceptional path, which the proposed new opcode is working around.</pre> </td> </tr> <tr> <th> <a href="#msg243037" id="msg243037">msg243037</a> - <a href="msg243037">(view)</a></th> <th>Author: Alyssa Coghlan (ncoghlan) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-13 05:19</th> </tr> <tr> <td colspan="4" class="content"> <pre>Avoiding WITH_CLEANUP entirely in the async case also sounds like a plausible approach. Either way, I'm also on IRC now if you want to thrash this out there.</pre> </td> </tr> <tr> <th> <a href="#msg243038" id="msg243038">msg243038</a> - <a href="msg243038">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-13 05:19</th> </tr> <tr> <td colspan="4" class="content"> <pre>I'd suggest you to look at ceval.c before <a href="https://www.python.org/dev/peps/pep-0492/">PEP 492</a> patch then (where there is just one WITH_CLEANUP opcode).</pre> </td> </tr> <tr> <th> <a href="#msg243041" id="msg243041">msg243041</a> - <a href="msg243041">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-05-13 05:54</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/e39fd5a8501a">e39fd5a8501a</a> by Nick Coghlan in branch 'default': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: fix for "async with" refcounting <a href="https://hg.python.org/cpython/rev/e39fd5a8501a">https://hg.python.org/cpython/rev/e39fd5a8501a</a></pre> </td> </tr> <tr> <th> <a href="#msg243042" id="msg243042">msg243042</a> - <a href="msg243042">(view)</a></th> <th>Author: Alyssa Coghlan (ncoghlan) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-13 06:06</th> </tr> <tr> <td colspan="4" class="content"> <pre>A bit more detail on the patch-as-merged: it has all of Yury's new tests, but the actual bug turned out to just be a missing INCREF/DECREF pair in WITH_CLEANUP_START and WITH_CLEANUP_FINISH. In the success case the reference counting errors cancelled each other out without causing a problem, as there was always a second live reference to the exception object on the stack. However, in the case where the awaitable threw an exception the standard exception handling machinery took care of removing the saved exception from the stack, and correctly decremented the reference count, which then caused problems due to the missing INCREF in WITH_CLEANUP_START.</pre> </td> </tr> <tr> <th> <a href="#msg243117" id="msg243117">msg243117</a> - <a href="msg243117">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-13 19:46</th> </tr> <tr> <td colspan="4" class="content"> <pre>Closing the issue. I'll open a new one for missing documentation. Thanks!</pre> </td> </tr> <tr> <th> <a href="#msg243118" id="msg243118">msg243118</a> - <a href="msg243118">(view)</a></th> <th>Author: Guido van Rossum (gvanrossum) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-13 19:49</th> </tr> <tr> <td colspan="4" class="content"> <pre>BTW, a shout out to Nick for doing most of the review for this monster patch. Thanks!</pre> </td> </tr> <tr> <th> <a href="#msg243119" id="msg243119">msg243119</a> - <a href="msg243119">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-05-13 20:49</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/0d80d46adfdb">0d80d46adfdb</a> by Yury Selivanov in branch 'default': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: More tests for 'async for' and 'async with'. <a href="https://hg.python.org/cpython/rev/0d80d46adfdb">https://hg.python.org/cpython/rev/0d80d46adfdb</a></pre> </td> </tr> <tr> <th> <a href="#msg243759" id="msg243759">msg243759</a> - <a href="msg243759">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-05-21 16:03</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/ff983ee10b3e">ff983ee10b3e</a> by Yury Selivanov in branch 'default': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: Use abc.Coroutine in inspect.iscoroutine() function <a href="https://hg.python.org/cpython/rev/ff983ee10b3e">https://hg.python.org/cpython/rev/ff983ee10b3e</a></pre> </td> </tr> <tr> <th> <a href="#msg244175" id="msg244175">msg244175</a> - <a href="msg244175">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-05-27 15:10</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/843fe7e831a8">843fe7e831a8</a> by Yury Selivanov in branch '3.5': <a class="closed" title="[closed] Lib/symbol.py is out of sync with Grammar/Grammar" href="issue24297">Issue 24297</a>: Update symbol.py. See also <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">issue 24017</a>. <a href="https://hg.python.org/cpython/rev/843fe7e831a8">https://hg.python.org/cpython/rev/843fe7e831a8</a> New changeset <a href="https://hg.python.org/lookup/87509d71653b">87509d71653b</a> by Yury Selivanov in branch 'default': <a class="closed" title="[closed] Lib/symbol.py is out of sync with Grammar/Grammar" href="issue24297">Issue 24297</a>: Update symbol.py. See also <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">issue 24017</a>. <a href="https://hg.python.org/cpython/rev/87509d71653b">https://hg.python.org/cpython/rev/87509d71653b</a></pre> </td> </tr> <tr> <th> <a href="#msg244252" id="msg244252">msg244252</a> - <a href="msg244252">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 03:30</th> </tr> <tr> <td colspan="4" class="content"> <pre>I added a couple of review comments to patch 6, but since no-one has responded so far, I guess they simply haven't been noticed. So I'll just repeat them here. 1) getawaitablefunc / aiternextfunc / getaiterfunc Is there a reason why these need to have their specific C type name instead of just reusing unaryfunc, or at least the existing iternextfunc / getiterfunc? They are unprefixed global names in the C namespace and I think we should be careful when adding more of those. 2) Awaitable.register(Coroutine) I think this is incorrect. A Coroutine is not Awaitable unless it also implements "__await__". How else should it be awaited? 3) I propose to use this wrapping code as a fallback for types.coroutine() in the case that a Generator (ABC) is passed instead of a generator (yield): class types_coroutine(object): def __init__(self, gen): self._gen = gen class as_coroutine(object): def __init__(self, gen): self._gen = gen self.send = gen.send self.throw = gen.throw self.close = gen.close def __await__(self): return self._gen def __call__(self, *args, **kwargs): return self.as_coroutine(self._gen(*args, **kwargs)) Note that the resulting Awaitable Coroutine type is not an Iterable. This differs from a (yield) coroutine, but it matches the Coroutine and Awaitable protocols, and the intention to separate both in order to avoid mistakes on user side. Additionally, regarding the tests: 4) def test_func_2(self): async def foo(): raise StopIteration with self.assertRaisesRegex( RuntimeError, "generator raised StopIteration"): run_async(foo()) Why is this actually necessary? I'm aware that it's also mentioned in the PEP, but is there an actual reason why a coroutine should behave the same as a generator here? Is it just an implementation detail for legacy reasons because generators and coroutines happen to share the same type implementation? (I don't think they need to, BTW.) 5) def test_func_8(self): @types.coroutine def bar(): return (yield from foo()) async def foo(): return 'spam' self.assertEqual(run_async(bar()), ([], 'spam') ) I find it surprising that this works at all. Yield-from iterates, and a coroutine is not supposed to be iterable, only awaitable (at least, that's what all error messages tell me when I try it). So why should "yield from" work on them? What if foo() was not an Iterable but a Coroutine? Should "yield from" then call "__await__" on it internally? I would find that *really* surprising, but given the above, I think it would be necessary to achieve consistency.</pre> </td> </tr> <tr> <th> <a href="#msg244257" id="msg244257">msg244257</a> - <a href="msg244257">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 03:54</th> </tr> <tr> <td colspan="4" class="content"> <pre>> 2) Awaitable.register(Coroutine) > I think this is incorrect. A Coroutine is not Awaitable unless it also implements "__await__". How else should it be awaited? It *is* correct, see <a href="https://www.python.org/dev/peps/pep-0492/">PEP 492</a>. Awaitable is either a coroutine *or* an object with an __await__ method. Generally, being an awaitable means that the object can be used in "await" expression. > 3) > I propose to use this wrapping code as a fallback for types.coroutine() in the case that a Generator (ABC) is passed instead of a generator (yield): Just implement tp_await/__await__ for coroutine-like objects coming from C-API or Cython. In general, iteration protocol is still the foundation for Future-like objects, so there is nothing wrong with this. Generator ABC isn't supposed to be used with "await" expression. > 4) > > def test_func_2(self): > async def foo(): > raise StopIteration > > with self.assertRaisesRegex( > RuntimeError, "generator raised StopIteration"): > > run_async(foo()) > Why is this actually necessary? I'm aware that it's also mentioned in the PEP, but is there an actual reason why a coroutine should behave the same as a generator here? Is it just an implementation detail for legacy reasons because generators and coroutines happen to share the same type implementation? (I don't think they need to, BTW.) Coroutines are implemented on top of generators. Until we clearly separate them (in 3.6?) I don't think we should allow coroutines to bubble up StopIteration. > 5) > def test_func_8(self): > @types.coroutine > def bar(): > return (yield from foo()) > > async def foo(): > return 'spam' > > self.assertEqual(run_async(bar()), ([], 'spam') ) > > I find it surprising that this works at all. Yield-from iterates, and a coroutine is not supposed to be iterable, only awaitable (at least, that's what all error messages tell me when I try it). So why should "yield from" work on them? What if foo() was not an Iterable but a Coroutine? Should "yield from" then call "__await__" on it internally? I would find that *really* surprising, but given the above, I think it would be necessary to achieve consistency. This is a special backwards-compatibility thing. In general, generators cannot yield-from coroutines (unless they are decorated with @types.coroutine).</pre> </td> </tr> <tr> <th> <a href="#msg244258" id="msg244258">msg244258</a> - <a href="msg244258">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 03:59</th> </tr> <tr> <td colspan="4" class="content"> <pre>Another question: is it ok if Cython implements and uses the "tp_as_async" slot in all Py3.x versions (3.2+)? It shouldn't hurt, but it would speed up async/await in Cython at least under Py3.x. Only Py2.6/7 would then have to resort to calling "__await__()" etc. at the Python level. One drawback is that Py<3.5 currently (needlessly) checks that "tp_reserved" and "tp_richcompare" are both implemented, but that can be worked around by also implementing the latter...</pre> </td> </tr> <tr> <th> <a href="#msg244261" id="msg244261">msg244261</a> - <a href="msg244261">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 04:18</th> </tr> <tr> <td colspan="4" class="content"> <pre>> It *is* correct, see <a href="https://www.python.org/dev/peps/pep-0492/">PEP 492</a>. Awaitable is either a coroutine *or* an object with an __await__ method. "coroutine", yes. But "Coroutine"? Shouldn't the Coroutine ABC then require "__await__" to be implemented? Maybe even by inheriting from Awaitable? > Just implement tp_await/__await__ for coroutine-like objects coming from C-API or Cython. Sure, that's how it's done. (Specifically, Coroutine is not an Iterable/Iterator, but its __await__() returns a thin Iterator that simply calls into the Generator code. A bit annoying and slowish, but that's what it takes.) I was just wondering how Cython should compile Python code that makes use of this decorator. The Coroutine and Generator types are separated in Cython now, and I think that's actually the right thing to do. This types.coroutine() decorator and special casing in CPython's code base gets a bit in the way here. > In general, iteration protocol is still the foundation for Future-like objects That's not really reflected in the ABCs, is it?</pre> </td> </tr> <tr> <th> <a href="#msg244264" id="msg244264">msg244264</a> - <a href="msg244264">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 04:35</th> </tr> <tr> <td colspan="4" class="content"> <pre>> > It *is* correct, see <a href="https://www.python.org/dev/peps/pep-0492/">PEP 492</a>. Awaitable is either a coroutine *or* an object with an __await__ > method. > > "coroutine", yes. But "Coroutine"? Shouldn't the Coroutine ABC then require > "__await__" to be implemented? Maybe even by inheriting from Awaitable? This is an interesting idea. Practically, when you register something as a Coroutine, you expect it to be compatible with ‘await’ expressions. And that’s only possible if __await__ is implemented. I’m curious what Guido and Nick think about this. I think that we can derive Coroutine from Awaitable. > > Just implement tp_await/__await__ for coroutine-like objects coming from C-API > or Cython. > > Sure, that's how it's done. (Specifically, Coroutine is not an > Iterable/Iterator, but its __await__() returns a thin Iterator that simply > calls into the Generator code. A bit annoying and slowish, but that's what > it takes.) Can't your Coroutine object return itself from its __await__, and implement __next__? Like genobject in CPython simply returns self from its __iter__. > I was just wondering how Cython should compile Python code that makes use > of this decorator. The Coroutine and Generator types are separated in > Cython now, and I think that's actually the right thing to do. This > types.coroutine() decorator and special casing in CPython's code base gets > a bit in the way here. I think we can update types.coroutine to continue using CO_ITERABLE_COROUTINE for pure python generator functions. And for something foreign we can use your proposed design. Would that be OK? > > > In general, iteration protocol is still the foundation for Future-like objects > > That's not really reflected in the ABCs, is it? Awaitable has its __await__ defined as a generator...</pre> </td> </tr> <tr> <th> <a href="#msg244268" id="msg244268">msg244268</a> - <a href="msg244268">(view)</a></th> <th>Author: Alyssa Coghlan (ncoghlan) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 05:10</th> </tr> <tr> <td colspan="4" class="content"> <pre>Thanks for highlighting these Stefan - you guessed correctly that I'd missed them on the review. For your first question, I agree getawaitablefunc / aiternextfunc / getaiterfunc should all be dropped and replaced with the existing "unaryfunc". For your second question, I agree it makes more sense for Coroutine to inherit from Awaitable than it does to have it registered with it. For the other three, I don't have a strong opinion, except that we should make sure that whatever we do on the CPython side works by default for Cython.</pre> </td> </tr> <tr> <th> <a href="#msg244269" id="msg244269">msg244269</a> - <a href="msg244269">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 05:12</th> </tr> <tr> <td colspan="4" class="content"> <pre>> For your first question, I agree getawaitablefunc / aiternextfunc / getaiterfunc should all be dropped and replaced with the existing "unaryfunc". I have no problem with that. But why do we have iternextfunc & getiterfunc (no "a" prefix)?</pre> </td> </tr> <tr> <th> <a href="#msg244273" id="msg244273">msg244273</a> - <a href="msg244273">(view)</a></th> <th>Author: Alyssa Coghlan (ncoghlan) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 05:35</th> </tr> <tr> <td colspan="4" class="content"> <pre>Given that tp_call is just "ternaryfunc", my guess would be "because when the iterator protocol was added, someone went with function-pointer-type-per-slot rather than function-pointer-type-per-call-signature". We *are* a little inconsistent here (e.g. "reprfunc" could also just use the "unaryfunc" signature), but Stefan's right that that isn't a good reason to *add* to the inconsistency.</pre> </td> </tr> <tr> <th> <a href="#msg244278" id="msg244278">msg244278</a> - <a href="msg244278">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 06:15</th> </tr> <tr> <td colspan="4" class="content"> <pre>> Can't your Coroutine object return itself from its __await__, and implement > __next__? Like genobject in CPython simply returns self from its __iter__. That was my first try, sure, and it mostly worked. It has a drawback, though: it's an incomplete implementation of the Iterator protocol. It's still (mostly) an Iterator, but not an Iterable, so it depends on how you use it whether you notice or not, and whether it works at all with other code or not. There's a test for a failing "next(coro)" in your test suite, for example, which would then not fail in Cython. OTOH, code cannot assume that calling iter() or for-looping over on an Iterable is a sane thing to do, because it doesn't work for Python's generator type based coroutine either, so we might get away with it... All of these little details make this trick appear like a potential source of subtle inconsistencies or incompatibilities. But given that there will almost certainly remain inconsistencies for compiled Python code, I'm not sure yet which approach is better. It's not impossible that I'll end up going back to the original design. I guess I'll eventually have to include some benchmarks in the decision. On a related note, my testing made me stumble over this code in asyncio.tasks.Task(): if coro.__class__ is types.GeneratorType: self._coro = coro else: self._coro = iter(coro) # Use the iterator just in case. This seems wrong regardless of how you look at it. And it definitely fails with both designs.</pre> </td> </tr> <tr> <th> <a href="#msg244280" id="msg244280">msg244280</a> - <a href="msg244280">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 06:28</th> </tr> <tr> <td colspan="4" class="content"> <pre>BTW, given that "iter(iterator)" works and returns the iterator, should we also allow "await x.__await__()" to work? I guess that would be tricky to achieve given that __await__() is only required to return any kind of arbitrary Iterator, and Iterators cannot be awaited due to deliberate restrictions. But it might be nice to have for wrapping purposes.</pre> </td> </tr> <tr> <th> <a href="#msg244281" id="msg244281">msg244281</a> - <a href="msg244281">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 06:48</th> </tr> <tr> <td colspan="4" class="content"> <pre>>> Yield-from iterates, and a coroutine is not supposed to be iterable, only awaitable (at least, that's what all error messages tell me when I try it). So why should "yield from" work on them? What if foo() was not an Iterable but a Coroutine? Should "yield from" then call "__await__" on it internally? I would find that *really* surprising, but given the above, I think it would be necessary to achieve consistency. > > This is a special backwards-compatibility thing. That only answers the half-serious first part of my question. ;) This code only works if foo() returns an Iterable, including a (yield) coroutine: @types.coroutine def bar(): return (yield from foo()) It does not work for arbitrary Coroutines as they are not iterable, but it might trick people into writing code that fails for non-coroutine Coroutines. I'd rather like to have this either work for any Coroutine or not at all.</pre> </td> </tr> <tr> <th> <a href="#msg244303" id="msg244303">msg244303</a> - <a href="msg244303">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-05-28 14:53</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/09327f653ec5">09327f653ec5</a> by Yury Selivanov in branch '3.4': asyncio: Drop some useless code from tasks.py. <a href="https://hg.python.org/cpython/rev/09327f653ec5">https://hg.python.org/cpython/rev/09327f653ec5</a> New changeset <a href="https://hg.python.org/lookup/adf72cffceb7">adf72cffceb7</a> by Yury Selivanov in branch '3.5': asyncio: Drop some useless code from tasks.py. <a href="https://hg.python.org/cpython/rev/adf72cffceb7">https://hg.python.org/cpython/rev/adf72cffceb7</a> New changeset <a href="https://hg.python.org/lookup/9c0a00247021">9c0a00247021</a> by Yury Selivanov in branch 'default': asyncio: Drop some useless code from tasks.py. <a href="https://hg.python.org/cpython/rev/9c0a00247021">https://hg.python.org/cpython/rev/9c0a00247021</a></pre> </td> </tr> <tr> <th> <a href="#msg244307" id="msg244307">msg244307</a> - <a href="msg244307">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-05-28 15:22</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/dfa0288c91fd">dfa0288c91fd</a> by Yury Selivanov in branch '3.5': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: Drop getawaitablefunc and friends in favor of unaryfunc. <a href="https://hg.python.org/cpython/rev/dfa0288c91fd">https://hg.python.org/cpython/rev/dfa0288c91fd</a> New changeset <a href="https://hg.python.org/lookup/99dcca3466d3">99dcca3466d3</a> by Yury Selivanov in branch 'default': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: Drop getawaitablefunc and friends in favor of unaryfunc. <a href="https://hg.python.org/cpython/rev/99dcca3466d3">https://hg.python.org/cpython/rev/99dcca3466d3</a></pre> </td> </tr> <tr> <th> <a href="#msg244319" id="msg244319">msg244319</a> - <a href="msg244319">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 16:42</th> </tr> <tr> <td colspan="4" class="content"> <pre>Stefan, I've already committed fixes for: 1. getawaitablefunc / aiternextfunc / getaiterfunc -> unaryfunc 2. strange code in tasks.py doing "coro = iter(coro)" is now removed I've also opened a couple of new issues (with patches for a review): 1. abc.Coroutine derived from abc.Awaitable: <a class="closed" title="[closed] collections.abc: Coroutine should be derived from Awaitable" href="issue24315">issue 24315</a> 2. types.coroutine() to support Cython objects: <a class="closed" title="[closed] Fix types.coroutine to accept objects from Cython" href="issue24316">issue 24316</a> I'll reply to some of your messages below: > Another question: is it ok if Cython implements and uses the "tp_as_async" slot in all Py3.x versions (3.2+)? It shouldn't hurt, [..] I think it's totally OK, given that you can workaround the drawback you mentioned. >> Can't your Coroutine object return itself from its __await__, and implement >> __next__? Like genobject in CPython simply returns self from its __iter__. > That was my first try, sure, and it mostly worked. It has a drawback, > though: it's an incomplete implementation of the Iterator protocol. It's > still (mostly) an Iterator, but not an Iterable, so it depends on how you > use it whether you notice or not, and whether it works at all with other > code or not. There's a test for a failing "next(coro)" in your test suite, > for example, which would then not fail in Cython. [..] I think if "next(cython_coro)" does not fail is acceptable. It's not ideal, but the purpose of Cython is to make Python code as fast as possible, so I'd try to avoid having any kind of "thin wrappers" around Cyhton coroutines.</pre> </td> </tr> <tr> <th> <a href="#msg244322" id="msg244322">msg244322</a> - <a href="msg244322">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-28 16:59</th> </tr> <tr> <td colspan="4" class="content"> <pre>Thanks Yury, I'll give it a try ASAP.</pre> </td> </tr> <tr> <th> <a href="#msg244374" id="msg244374">msg244374</a> - <a href="msg244374">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-29 13:08</th> </tr> <tr> <td colspan="4" class="content"> <pre>Stefan, Because of <a href="https://mail.python.org/pipermail/python-committers/2015-May/003410.html">https://mail.python.org/pipermail/python-committers/2015-May/003410.html</a> I've decided to commit 24315 and 24316 today. Please try to check that everything works before new beta 2.</pre> </td> </tr> <tr> <th> <a href="#msg244384" id="msg244384">msg244384</a> - <a href="msg244384">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-29 15:09</th> </tr> <tr> <td colspan="4" class="content"> <pre>Tried it, works for me. Thanks!</pre> </td> </tr> <tr> <th> <a href="#msg244385" id="msg244385">msg244385</a> - <a href="msg244385">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-05-29 15:14</th> </tr> <tr> <td colspan="4" class="content"> <pre>> Tried it, works for me. Thanks! This is really good news! Thanks!</pre> </td> </tr> <tr> <th> <a href="#msg244567" id="msg244567">msg244567</a> - <a href="msg244567">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-06-01 01:37</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/0708aabefb55">0708aabefb55</a> by Yury Selivanov in branch '3.4': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: Fix asyncio.CoroWrapper to support 'async def' coroutines <a href="https://hg.python.org/cpython/rev/0708aabefb55">https://hg.python.org/cpython/rev/0708aabefb55</a> New changeset <a href="https://hg.python.org/lookup/1dc232783012">1dc232783012</a> by Yury Selivanov in branch '3.5': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: Fix asyncio.CoroWrapper to support 'async def' coroutines <a href="https://hg.python.org/cpython/rev/1dc232783012">https://hg.python.org/cpython/rev/1dc232783012</a> New changeset <a href="https://hg.python.org/lookup/2e7c45560c38">2e7c45560c38</a> by Yury Selivanov in branch 'default': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: Fix asyncio.CoroWrapper to support 'async def' coroutines <a href="https://hg.python.org/cpython/rev/2e7c45560c38">https://hg.python.org/cpython/rev/2e7c45560c38</a></pre> </td> </tr> <tr> <th> <a href="#msg244568" id="msg244568">msg244568</a> - <a href="msg244568">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-06-01 01:44</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/a0a699b828e7">a0a699b828e7</a> by Yury Selivanov in branch '3.5': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: Add a test for CoroWrapper and 'async def' coroutines <a href="https://hg.python.org/cpython/rev/a0a699b828e7">https://hg.python.org/cpython/rev/a0a699b828e7</a> New changeset <a href="https://hg.python.org/lookup/89521ac669f0">89521ac669f0</a> by Yury Selivanov in branch 'default': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: Add a test for CoroWrapper and 'async def' coroutines <a href="https://hg.python.org/cpython/rev/89521ac669f0">https://hg.python.org/cpython/rev/89521ac669f0</a></pre> </td> </tr> <tr> <th> <a href="#msg244596" id="msg244596">msg244596</a> - <a href="msg244596">(view)</a></th> <th>Author: Roundup Robot (python-dev) <img src="@@file/triager.png" title="Python triager" alt="(Python triager)" /></th> <th>Date: 2015-06-01 16:16</th> </tr> <tr> <td colspan="4" class="content"> <pre>New changeset <a href="https://hg.python.org/lookup/1e9e0664ee9b">1e9e0664ee9b</a> by Yury Selivanov in branch '3.5': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: Make PyEval_(Set|Get)CoroutineWrapper private <a href="https://hg.python.org/cpython/rev/1e9e0664ee9b">https://hg.python.org/cpython/rev/1e9e0664ee9b</a> New changeset <a href="https://hg.python.org/lookup/6fcb64097b1c">6fcb64097b1c</a> by Yury Selivanov in branch 'default': <a class="closed" title="[closed] Implemenation of the PEP 492 - Coroutines with async and await syntax" href="issue24017">Issue 24017</a>: Make PyEval_(Set|Get)CoroutineWrapper private <a href="https://hg.python.org/cpython/rev/6fcb64097b1c">https://hg.python.org/cpython/rev/6fcb64097b1c</a></pre> </td> </tr> <tr> <th> <a href="#msg244759" id="msg244759">msg244759</a> - <a href="msg244759">(view)</a></th> <th>Author: Alex Grönholm (alex.gronholm) <span title="Contributor form received">*</span></th> <th>Date: 2015-06-03 15:16</th> </tr> <tr> <td colspan="4" class="content"> <pre>Was __await__() deliberately left out of concurrent.futures.Future or was that an oversight? Or am I misunderstanding something?</pre> </td> </tr> <tr> <th> <a href="#msg244761" id="msg244761">msg244761</a> - <a href="msg244761">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-06-03 15:18</th> </tr> <tr> <td colspan="4" class="content"> <pre>> Was __await__() deliberately left out of concurrent.futures.Future or was that an oversight? Or am I misunderstanding something? I don't think concurrent.Future is supposed to be used with asyncio (in 'yield from' or 'await' expressions).</pre> </td> </tr> <tr> <th> <a href="#msg244799" id="msg244799">msg244799</a> - <a href="msg244799">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-06-04 05:30</th> </tr> <tr> <td colspan="4" class="content"> <pre>Hmm, but IMHO a) the new syntax isn't just for asyncio and b) awaiting a Future seems like a *very* reasonable thing to do. I think opening a new ticket for this is a good idea.</pre> </td> </tr> <tr> <th> <a href="#msg244818" id="msg244818">msg244818</a> - <a href="msg244818">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-06-04 13:06</th> </tr> <tr> <td colspan="4" class="content"> <pre>> Hmm, but IMHO a) the new syntax isn't just for asyncio and b) awaiting a Future seems like a *very* reasonable thing to do. I think opening a new ticket for this is a good idea. Stefan, I honestly have bo idea what concurrent.Future.__await__ would do. There is no loop for concurrent module. If you have a patch with tests in mind, please open a separate issue (targeting 3.6).</pre> </td> </tr> <tr> <th> <a href="#msg244826" id="msg244826">msg244826</a> - <a href="msg244826">(view)</a></th> <th>Author: Guido van Rossum (gvanrossum) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-06-04 15:05</th> </tr> <tr> <td colspan="4" class="content"> <pre>Maybe it's possible to give an interpretation to awaiting on a threaded Future? __await__ could return a new asyncio Future, and add a completion callback to the original Future that makes the asyncio Future ready and transfers the result/exception. This would have to use loop.call_soon_threadsafe() to transfer control from the exector thread to the thread where the loop is running. The only thing I don't know is whether it's possible for __await__ to return a Future.</pre> </td> </tr> <tr> <th> <a href="#msg244831" id="msg244831">msg244831</a> - <a href="msg244831">(view)</a></th> <th>Author: Yury Selivanov (yselivanov) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-06-04 15:38</th> </tr> <tr> <td colspan="4" class="content"> <pre>Guido, Stefen, please see <a class="closed" title="[closed] consider implementing __await__ on concurrent.futures.Future" href="issue24383">issue24383</a>.</pre> </td> </tr> <tr> <th> <a href="#msg245075" id="msg245075">msg245075</a> - <a href="msg245075">(view)</a></th> <th>Author: Stefan Behnel (scoder) <span title="Contributor form received">*</span> <img src="@@file/committer.png" title="Python committer" alt="(Python committer)" /></th> <th>Date: 2015-06-09 17:11</th> </tr> <tr> <td colspan="4" class="content"> <pre>See <a class="closed" title="[closed] Awaitable ABC incompatible with functools.singledispatch" href="issue24400">issue 24400</a> regarding a split of yield-based generators and async-def coroutines at a type level.</pre> </td> </tr> </table> <table class="history table table-condensed table-striped"><tr><th colspan="4" class="header"> History </th></tr><tr> <th>Date</th> <th>User</th> <th>Action</th> <th>Args</th> </tr> <tr><td>2022-04-11 14:58:15</td><td>admin</td><td>set</td><td>nosy: + <a rel="nofollow" href="user2731">larry</a><br />github: 68205<br /></td></tr> <tr><td>2015-06-20 19:39:53</td><td>yselivanov</td><td>set</td><td>dependencies: + <a rel="nofollow" href="issue24400">Awaitable ABC incompatible with functools.singledispatch</a></td></tr> <tr><td>2015-06-09 17:11:27</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg245075">msg245075</a></td></tr> <tr><td>2015-06-04 15:38:35</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244831">msg244831</a></td></tr> <tr><td>2015-06-04 15:05:57</td><td>gvanrossum</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244826">msg244826</a></td></tr> <tr><td>2015-06-04 13:06:12</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244818">msg244818</a></td></tr> <tr><td>2015-06-04 05:30:28</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244799">msg244799</a></td></tr> <tr><td>2015-06-03 15:18:53</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244761">msg244761</a></td></tr> <tr><td>2015-06-03 15:16:08</td><td>alex.gronholm</td><td>set</td><td>nosy: + <a rel="nofollow" href="user10974">alex.gronholm</a><br />messages: + <a rel="nofollow" href="msg244759">msg244759</a><br /></td></tr> <tr><td>2015-06-01 16:16:03</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244596">msg244596</a></td></tr> <tr><td>2015-06-01 01:44:22</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244568">msg244568</a></td></tr> <tr><td>2015-06-01 01:37:45</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244567">msg244567</a></td></tr> <tr><td>2015-05-29 15:14:35</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244385">msg244385</a></td></tr> <tr><td>2015-05-29 15:09:41</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244384">msg244384</a></td></tr> <tr><td>2015-05-29 13:08:12</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244374">msg244374</a></td></tr> <tr><td>2015-05-28 16:59:00</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244322">msg244322</a></td></tr> <tr><td>2015-05-28 16:42:29</td><td>yselivanov</td><td>set</td><td>dependencies: + <a rel="nofollow" href="issue24316">Fix types.coroutine to accept objects from Cython</a><br />messages: + <a rel="nofollow" href="msg244319">msg244319</a></td></tr> <tr><td>2015-05-28 15:22:52</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244307">msg244307</a></td></tr> <tr><td>2015-05-28 15:13:46</td><td>yselivanov</td><td>set</td><td>dependencies: + <a rel="nofollow" href="issue24315">collections.abc: Coroutine should be derived from Awaitable</a></td></tr> <tr><td>2015-05-28 14:53:26</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244303">msg244303</a></td></tr> <tr><td>2015-05-28 06:48:01</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244281">msg244281</a></td></tr> <tr><td>2015-05-28 06:28:36</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244280">msg244280</a></td></tr> <tr><td>2015-05-28 06:15:15</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244278">msg244278</a></td></tr> <tr><td>2015-05-28 05:35:53</td><td>ncoghlan</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244273">msg244273</a></td></tr> <tr><td>2015-05-28 05:12:50</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244269">msg244269</a></td></tr> <tr><td>2015-05-28 05:10:10</td><td>ncoghlan</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244268">msg244268</a></td></tr> <tr><td>2015-05-28 04:35:16</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244264">msg244264</a></td></tr> <tr><td>2015-05-28 04:18:30</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244261">msg244261</a></td></tr> <tr><td>2015-05-28 03:59:56</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244258">msg244258</a></td></tr> <tr><td>2015-05-28 03:54:41</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244257">msg244257</a></td></tr> <tr><td>2015-05-28 03:30:02</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244252">msg244252</a></td></tr> <tr><td>2015-05-27 15:10:14</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg244175">msg244175</a></td></tr> <tr><td>2015-05-21 16:03:49</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg243759">msg243759</a></td></tr> <tr><td>2015-05-14 03:27:38</td><td>yselivanov</td><td>set</td><td>dependencies: + <a rel="nofollow" href="issue24184">PEP 492: Add AsyncIterator and AsyncIterable to collections.abc</a></td></tr> <tr><td>2015-05-13 20:49:55</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg243119">msg243119</a></td></tr> <tr><td>2015-05-13 19:49:27</td><td>gvanrossum</td><td>set</td><td>messages: + <a rel="nofollow" href="msg243118">msg243118</a></td></tr> <tr><td>2015-05-13 19:47:52</td><td>yselivanov</td><td>set</td><td>dependencies: + <a rel="nofollow" href="issue24180">PEP 492: Documentation</a></td></tr> <tr><td>2015-05-13 19:46:15</td><td>yselivanov</td><td>set</td><td>status: open -> closed<br />messages: + <a rel="nofollow" href="msg243117">msg243117</a><br /><br />components: + Interpreter Core<br />resolution: fixed<br />stage: patch review -> resolved</td></tr> <tr><td>2015-05-13 06:06:45</td><td>ncoghlan</td><td>set</td><td>messages: + <a rel="nofollow" href="msg243042">msg243042</a></td></tr> <tr><td>2015-05-13 05:54:16</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg243041">msg243041</a></td></tr> <tr><td>2015-05-13 05:19:52</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg243038">msg243038</a></td></tr> <tr><td>2015-05-13 05:19:39</td><td>ncoghlan</td><td>set</td><td>messages: + <a rel="nofollow" href="msg243037">msg243037</a></td></tr> <tr><td>2015-05-13 05:15:50</td><td>ncoghlan</td><td>set</td><td>messages: + <a rel="nofollow" href="msg243036">msg243036</a></td></tr> <tr><td>2015-05-13 05:10:43</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg243035">msg243035</a></td></tr> <tr><td>2015-05-13 05:00:58</td><td>ncoghlan</td><td>set</td><td>messages: + <a rel="nofollow" href="msg243033">msg243033</a></td></tr> <tr><td>2015-05-13 03:36:03</td><td>yselivanov</td><td>set</td><td>files: + <a rel="nofollow" href="file39354">with.patch</a><br /><br />messages: + <a rel="nofollow" href="msg243031">msg243031</a></td></tr> <tr><td>2015-05-12 18:28:40</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242984">msg242984</a></td></tr> <tr><td>2015-05-12 15:46:02</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242982">msg242982</a></td></tr> <tr><td>2015-05-12 15:30:46</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242979">msg242979</a></td></tr> <tr><td>2015-05-12 04:06:39</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242938">msg242938</a></td></tr> <tr><td>2015-05-12 03:23:40</td><td>gvanrossum</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242937">msg242937</a></td></tr> <tr><td>2015-05-12 03:06:30</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242936">msg242936</a></td></tr> <tr><td>2015-05-12 03:03:22</td><td>python-dev</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242935">msg242935</a></td></tr> <tr><td>2015-05-12 02:31:32</td><td>python-dev</td><td>set</td><td>nosy: + <a rel="nofollow" href="user13902">python-dev</a><br />messages: + <a rel="nofollow" href="msg242931">msg242931</a><br /></td></tr> <tr><td>2015-05-12 00:16:54</td><td>ncoghlan</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242928">msg242928</a></td></tr> <tr><td>2015-05-12 00:03:04</td><td>ncoghlan</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242927">msg242927</a></td></tr> <tr><td>2015-05-11 19:59:43</td><td>yselivanov</td><td>set</td><td>files: + <a rel="nofollow" href="file39344">await_06.patch</a><br /><br />messages: + <a rel="nofollow" href="msg242912">msg242912</a></td></tr> <tr><td>2015-05-11 01:33:02</td><td>yselivanov</td><td>set</td><td>files: + <a rel="nofollow" href="file39337">await_05.patch</a><br /><br />messages: + <a rel="nofollow" href="msg242877">msg242877</a></td></tr> <tr><td>2015-05-10 21:25:37</td><td>yselivanov</td><td>set</td><td>dependencies: + <a rel="nofollow" href="issue24018">add a Generator ABC</a></td></tr> <tr><td>2015-05-10 17:40:40</td><td>asvetlov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242862">msg242862</a></td></tr> <tr><td>2015-05-10 16:21:44</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242860">msg242860</a></td></tr> <tr><td>2015-05-10 03:34:08</td><td>ncoghlan</td><td>set</td><td>nosy: + <a rel="nofollow" href="user1309">ncoghlan</a><br />messages: + <a rel="nofollow" href="msg242848">msg242848</a><br /></td></tr> <tr><td>2015-05-09 03:29:49</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242793">msg242793</a></td></tr> <tr><td>2015-05-08 21:15:24</td><td>yselivanov</td><td>set</td><td>files: + <a rel="nofollow" href="file39325">await_04.patch</a><br /><br />messages: + <a rel="nofollow" href="msg242779">msg242779</a></td></tr> <tr><td>2015-05-07 20:13:29</td><td>yselivanov</td><td>set</td><td>files: + <a rel="nofollow" href="file39314">await_03.patch</a><br /><br />messages: + <a rel="nofollow" href="msg242731">msg242731</a></td></tr> <tr><td>2015-05-06 00:16:22</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242627">msg242627</a></td></tr> <tr><td>2015-05-06 00:05:54</td><td>yselivanov</td><td>set</td><td>priority: normal -> release blocker</td></tr> <tr><td>2015-05-06 00:05:25</td><td>yselivanov</td><td>set</td><td>dependencies: + <a rel="nofollow" href="issue2292">Missing *-unpacking generalizations</a></td></tr> <tr><td>2015-05-01 15:18:54</td><td>gvanrossum</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242326">msg242326</a></td></tr> <tr><td>2015-05-01 12:19:22</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242304">msg242304</a></td></tr> <tr><td>2015-04-27 19:52:07</td><td>gvanrossum</td><td>set</td><td>nosy: + <a rel="nofollow" href="user5">gvanrossum</a><br /></td></tr> <tr><td>2015-04-26 23:27:49</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242086">msg242086</a></td></tr> <tr><td>2015-04-26 17:27:56</td><td>yselivanov</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242064">msg242064</a></td></tr> <tr><td>2015-04-26 15:11:00</td><td>scoder</td><td>set</td><td>messages: + <a rel="nofollow" href="msg242056">msg242056</a></td></tr> <tr><td>2015-04-21 04:03:40</td><td>yselivanov</td><td>set</td><td>assignee: <a rel="nofollow" href="user16198">yselivanov</a></td></tr> <tr><td>2015-04-21 03:59:19</td><td>yselivanov</td><td>set</td><td>files: + <a rel="nofollow" href="file39155">await_02.patch</a><br /><br />messages: + <a rel="nofollow" href="msg241697">msg241697</a></td></tr> <tr><td>2015-04-21 00:53:09</td><td>yselivanov</td><td>set</td><td>dependencies: + <a rel="nofollow" href="issue22906">PEP 479: Change StopIteration handling inside generators</a></td></tr> <tr><td>2015-04-20 21:43:13</td><td>vstinner</td><td>set</td><td>messages: + <a rel="nofollow" href="msg241687">msg241687</a></td></tr> <tr><td>2015-04-20 19:56:16</td><td>yselivanov</td><td>set</td><td>files: - <a rel="nofollow" href="file39149">await_01.patch</a></td></tr> <tr><td>2015-04-20 19:55:43</td><td>yselivanov</td><td>set</td><td>files: + <a rel="nofollow" href="file39149">await_01.patch</a></td></tr> <tr><td>2015-04-20 19:55:22</td><td>yselivanov</td><td>set</td><td>files: + <a rel="nofollow" href="file39148">await_01.patch</a><br /><br />messages: + <a rel="nofollow" href="msg241679">msg241679</a></td></tr> <tr><td>2015-04-20 19:55:02</td><td>yselivanov</td><td>set</td><td>files: - <a rel="nofollow" href="file39147">async_01.patch</a></td></tr> <tr><td>2015-04-20 19:45:38</td><td>yselivanov</td><td>set</td><td>files: + <a rel="nofollow" href="file39147">async_01.patch</a><br />keywords: + <a rel="nofollow" href="keyword2">patch</a><br />messages: + <a rel="nofollow" href="msg241678">msg241678</a><br /><br />stage: patch review</td></tr> <tr><td>2015-04-20 19:43:04</td><td>vstinner</td><td>set</td><td>hgrepos: - hgrepo306</td></tr> <tr><td>2015-04-20 19:38:45</td><td>scoder</td><td>set</td><td>nosy: + <a rel="nofollow" href="user2153">scoder</a><br />type: enhancement<br /></td></tr> <tr><td>2015-04-20 19:37:47</td><td>yselivanov</td><td>set</td><td>nosy: + <a rel="nofollow" href="user10303">asvetlov</a>, <a rel="nofollow" href="user16198">yselivanov</a><br /></td></tr> <tr><td>2015-04-20 19:34:02</td><td>vstinner</td><td>set</td><td>hgrepos: + hgrepo306</td></tr> <tr><td>2015-04-20 19:33:55</td><td>vstinner</td><td>create</td><td></td></tr> </table> </div> </div> <!-- content-body --> <div id="footer"> <div id="credits"> Supported by <a href="https://python.org/psf-landing/" title="The Python Software Foundation">The Python Software Foundation</a>, <br> Powered by <a href="http://roundup.sourceforge.net" title="Powered by the Roundup Issue Tracker">Roundup</a> </div> <!-- credits --> Copyright © 1990-2022, <a href="http://python.org/psf">Python Software Foundation</a><br /> <a href="http://python.org/about/legal">Legal Statements</a> </div> <!-- footer --> </div> <!-- body-main --> </div> <!-- content --> </body> </html>