This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Misleading example in sys.set_coroutine_wrapper docs
Type: enhancement Stage: resolved
Components: Documentation Versions: Python 3.7, Python 3.6
process
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: docs@python Nosy List: carlbordum, docs@python, giampaolo.rodola, ncoghlan, vstinner, yselivanov
Priority: normal Keywords:

Created on 2017-06-06 02:44 by ncoghlan, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (3)
msg295231 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2017-06-06 02:44
In issue 24342, the invocation of coroutine wrappers specified via sys.set_coroutine_wrapper was fixed to catch and report the case of infinite recursion, where the wrapper attempts to instantiate a nested coroutine (which would call the wrapper, which would attempt to instantiate the coroutine, etc, etc)

The docs for sys.set_coroutine_wrapper include an example of this failure case: https://docs.python.org/3/library/sys.html#sys.set_coroutine_wrapper

However, if you're not reading carefully, it looks like an example of how to *use* sys.set_coroutine_wrapper, rather than an example of a case that won't work.

It would be better to include an example that either doesn't wrap the coroutine at all, or else uses one of the non-native coroutine emulations to avoid the infinite recursion problem:

```
import asyncio, sys

def wrapper(coro):
    @asyncio.coroutine
    def wrap(coro):
        print("Coroutine started")
        result = yield from coro
        print("Coroutine finished")
        return result
    return wrap(coro)

sys.set_coroutine_wrapper(wrapper)

async def foo():
    print("Coroutine running")
    return "Coroutine result"

import asyncio
asyncio.get_event_loop().run_until_complete(foo())
```

Also related: I discovered in writing this that "sys.set_coroutine_wrapper(None)" doesn't actually turn off coroutine wrapping. Instead, you still get this exception when attempting to recursively define an unwrapped one:

RuntimeError: coroutine wrapper <NULL> attempted to recursively wrap <code object wrap at 0x7eff31fbde40, file "<stdin>", line 2>)

That error was produced as follows:

```
import sys, contextlib

@contextlib.contextmanager
def disable_coroutine_wrapping():
    wrapper = sys.get_coroutine_wrapper()
    sys.set_coroutine_wrapper(None)
    try:
        yield
    finally:
        sys.set_coroutine_wrapper(wrapper)

def wrapper(coro):
    async def wrap(coro):
        print("Coroutine started")
        result = await coro
        print("Coroutine finished")
        return result
    with disable_coroutine_wrapping():
        return wrap(coro)

sys.set_coroutine_wrapper(wrapper)

async def foo():
    print("Coroutine running")
    return "Coroutine result"

import asyncio
asyncio.get_event_loop().run_until_complete(foo())
```
msg377937 - (view) Author: Carl Bordum Hansen (carlbordum) * Date: 2020-10-04 12:44
I think this can be closed as `sys.set_coroutine_wrapper` was removed in https://bugs.python.org/issue36933
msg378007 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-10-05 09:04
Right, I close the issue.
History
Date User Action Args
2022-04-11 14:58:47adminsetgithub: 74763
2020-10-05 09:04:52vstinnersetstatus: open -> closed
resolution: out of date
messages: + msg378007

stage: needs patch -> resolved
2020-10-04 12:44:34carlbordumsetnosy: + carlbordum
messages: + msg377937
2017-06-06 02:44:33ncoghlancreate