- Python Home
- About
- News
- Documentation
- Downloads
- Community
- Foundation
- Developer's Guide
- Issue Tracker
- Issues
- Summaries
- User
- Administration
- Help
Issue37743
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.
Created on 2019-08-01 23:33 by Antony.Lee, last changed 2022-04-11 14:59 by admin.
| Messages (2) | |||
|---|---|---|---|
| msg348878 - (view) | Author: Antony Lee (Antony.Lee) * | Date: 2019-08-01 23:33 | |
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?
|
|||
| msg351074 - (view) | Author: Alyssa Coghlan (ncoghlan) * ![]() |
Date: 2019-09-03 08:25 | |
This is a documentation bug, as the current behaviour is as intended, but the documented equivalence doesn't hold for generator functions: for a generator function, the CM will only be applied when the generator is instantiated, whereas the inline context manager version will be held open until the generator is closed or destroyed. That said, an approach similar to the one discussed in #37398 could also be applied, here, with a separate "ContextDecorator.generator()" class method added to give the "wrapped yield from" behaviour. If anyone is interested in pursuing that, it can be filed as a separate enhancement issue (leaving this bug to cover the fact that the existing documentation is only accurate for regular synchronous functions) |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022-04-11 14:59:18 | admin | set | github: 81924 |
| 2019-09-03 10:21:10 | Antony.Lee | set | nosy:
- Antony.Lee |
| 2019-09-03 08:25:36 | ncoghlan | set | assignee: ncoghlan -> messages: + msg351074 components: + Documentation, - Library (Lib) |
| 2019-08-02 06:15:52 | rhettinger | set | assignee: ncoghlan |
| 2019-08-02 01:41:37 | xtreak | set | nosy:
+ ncoghlan |
| 2019-08-01 23:33:04 | Antony.Lee | create | |


