New submission from Nick Coghlan:

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())
```

----------
assignee: docs@python
components: Documentation
messages: 295231
nosy: docs@python, giampaolo.rodola, haypo, ncoghlan, yselivanov
priority: normal
severity: normal
stage: needs patch
status: open
title: Misleading example in sys.set_coroutine_wrapper docs
type: enhancement
versions: Python 3.6, Python 3.7

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue30578>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to