[issue37743] How should contextmanager/ContextDecorator work with generators?
Antony Lee
report at bugs.python.org
Thu Aug 1 19:33:04 EDT 2019
New submission from Antony Lee <anntzer.lee at gmail.com>:
The docs for ContextDecorator (of which contextmanager is a case) describe its semantics as:
... for any construct of the following form:
def f():
with cm():
# Do stuff
ContextDecorator lets you instead write:
@cm()
def f():
# Do stuff
However, when decorating a generator, the equivalence is broken:
from contextlib import contextmanager
@contextmanager
def cm():
print("start")
yield
print("stop")
def gen_using_with():
with cm():
yield from map(print, range(2))
@cm()
def gen_using_decorator():
yield from map(print, range(2))
print("using with")
list(gen_using_with())
print("==========")
print("using decorator")
list(gen_using_decorator())
results in
using with
start
0
1
stop
==========
using decorator
start
stop
0
1
i.e., when used as a decorator, the entire contextmanager is executed first before iterating over the generator (which is unsurprising given the implementation of ContextDecorator: ContextDecorator returns a function that executes the context manager and returns the generator, which is only iterated over later).
Should this be considered as a bug in ContextDecorator, and should ContextDecorator instead detect when it is used to decorate a generator (e.g. with inspect.isgeneratorfunction), and switch its implementation accordingly in that case?
----------
components: Library (Lib)
messages: 348878
nosy: Antony.Lee
priority: normal
severity: normal
status: open
title: How should contextmanager/ContextDecorator work with generators?
versions: Python 3.8
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue37743>
_______________________________________
More information about the Python-bugs-list
mailing list