cpython: b23d1df7e47e (original) (raw)
Mercurial > cpython
changeset 69850:b23d1df7e47e
Merge #11647 update from 3.2 [#11647]
Nick Coghlan ncoghlan@gmail.com | |
---|---|
date | Thu, 05 May 2011 23:58:57 +1000 |
parents | 97004f70ff0d(current diff)e4ba097123f6(diff) |
children | b06d7aa8ac20 |
files | Misc/ACKS Misc/NEWS |
diffstat | 6 files changed, 50 insertions(+), 10 deletions(-)[+] [-] Doc/library/contextlib.rst 14 Lib/contextlib.py 28 Lib/test/test_contextlib.py 7 Lib/test/test_with.py 6 Misc/ACKS 1 Misc/NEWS 4 |
line wrap: on
line diff
--- a/Doc/library/contextlib.rst
+++ b/Doc/library/contextlib.rst
@@ -54,8 +54,12 @@ Functions provided:
the exception has been handled, and execution will resume with the statement
immediately following the :keyword:with
statement.
- contextmanager uses :class:
ContextDecorator
so the context managers it - creates can be used as decorators as well as in :keyword:
with
statements.
- :func:
contextmanager
uses :class:ContextDecorator
so the context managers - it creates can be used as decorators as well as in :keyword:
with
statements. - When used as a decorator, a new generator instance is implicitly created on
- each function call (this allows the otherwise "one-shot" context managers
- created by :func:
contextmanager
to meet the requirement that context - managers support multiple invocations in order to be used as decorators).
.. versionchanged:: 3.2
Use of :class:
ContextDecorator
. @@ -155,6 +159,12 @@ Functions provided: def exit(self, *exc): return False
- .. note::
As the decorated function must be able to be called multiple times, the[](#l1.23)
underlying context manager must support use in multiple :keyword:`with`[](#l1.24)
statements. If this is not the case, then the original construct with the[](#l1.25)
explicit :keyword:`with` statement inside the function should be used.[](#l1.26)
--- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -9,10 +9,23 @@ from warnings import warn class ContextDecorator(object): "A base class or mixin that enables context managers to work as decorators." +
- def _recreate_cm(self):
"""Return a recreated instance of self.[](#l2.9)
[](#l2.10)
Allows otherwise one-shot context managers like[](#l2.11)
_GeneratorContextManager to support use as[](#l2.12)
decorators via implicit recreation.[](#l2.13)
[](#l2.14)
Note: this is a private interface just for _GCM in 3.2 but will be[](#l2.15)
renamed and documented for third party use in 3.3[](#l2.16)
"""[](#l2.17)
return self[](#l2.18)
+ def call(self, func): @wraps(func) def inner(*args, **kwds):
with self:[](#l2.23)
with self._recreate_cm():[](#l2.24) return func(*args, **kwds)[](#l2.25) return inner[](#l2.26)
@@ -20,8 +33,15 @@ class ContextDecorator(object): class _GeneratorContextManager(ContextDecorator): """Helper for @contextmanager decorator."""
- def init(self, func, *args, **kwds):
self.gen = func(*args, **kwds)[](#l2.35)
self.func, self.args, self.kwds = func, args, kwds[](#l2.36)
- def _recreate_cm(self):
# _GCM instances are one-shot context managers, so the[](#l2.39)
# CM must be recreated each time a decorated function is[](#l2.40)
# called[](#l2.41)
return self.__class__(self.func, *self.args, **self.kwds)[](#l2.42)
def enter(self): try: @@ -92,7 +112,7 @@ def contextmanager(func): """ @wraps(func) def helper(*args, **kwds):
return _GeneratorContextManager(func(*args, **kwds))[](#l2.50)
--- a/Lib/test/test_contextlib.py +++ b/Lib/test/test_contextlib.py @@ -350,13 +350,13 @@ class TestContextDecorator(unittest.Test def test_contextmanager_as_decorator(self):
state = [][](#l3.7) @contextmanager[](#l3.8) def woohoo(y):[](#l3.9) state.append(y)[](#l3.10) yield[](#l3.11) state.append(999)[](#l3.12)
state = [][](#l3.14) @woohoo(1)[](#l3.15) def test(x):[](#l3.16) self.assertEqual(state, [1])[](#l3.17)
@@ -364,6 +364,11 @@ class TestContextDecorator(unittest.Test test('something') self.assertEqual(state, [1, 'something', 999])
# Issue #11647: Ensure the decorated function is 'reusable'[](#l3.22)
state = [][](#l3.23)
test('something else')[](#l3.24)
self.assertEqual(state, [1, 'something else', 999])[](#l3.25)
This is needed to make the test actually run under regrtest.py
--- a/Lib/test/test_with.py +++ b/Lib/test/test_with.py @@ -14,8 +14,8 @@ from test.support import run_unittest class MockContextManager(_GeneratorContextManager):
- def init(self, func, *args, **kwds):
super().__init__(func, *args, **kwds)[](#l4.10) self.enter_called = False[](#l4.11) self.exit_called = False[](#l4.12) self.exit_args = None[](#l4.13)
@@ -33,7 +33,7 @@ class MockContextManager(_GeneratorConte def mock_contextmanager(func): def helper(*args, **kwds):
return MockContextManager(func(*args, **kwds))[](#l4.18)
--- a/Misc/ACKS +++ b/Misc/ACKS @@ -709,6 +709,7 @@ Burton Radons Brodie Rao Antti Rasinen Sridhar Ratnakumar +Ysj Ray Eric Raymond Edward K. Ream Chris Rebert
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -140,6 +140,10 @@ Core and Builtins Library ------- +- Issue #11647: objects created using contextlib.contextmanager now support