From 101ff3541cbe5bd9549722dc53c28d6c21b9389c Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 28 Jun 2015 17:06:07 +0300 Subject: [PATCH] Issue #24336: The contextmanager decorator now works with functions with keyword arguments called "func" and "self". Patch by Martin Panter. --- Lib/contextlib.py | 6 +++--- Lib/test/test_contextlib.py | 8 ++++++++ Lib/test/test_with.py | 6 +++--- Misc/NEWS | 3 +++ 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Lib/contextlib.py b/Lib/contextlib.py index 82ee955a8b2..07b22611150 100644 --- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -34,7 +34,7 @@ class ContextDecorator(object): class _GeneratorContextManager(ContextDecorator): """Helper for @contextmanager decorator.""" - def __init__(self, func, *args, **kwds): + def __init__(self, func, args, kwds): self.gen = func(*args, **kwds) self.func, self.args, self.kwds = func, args, kwds # Issue 19330: ensure context manager instances have good docstrings @@ -52,7 +52,7 @@ class _GeneratorContextManager(ContextDecorator): # _GCM instances are one-shot context managers, so the # CM must be recreated each time a decorated function is # called - return self.__class__(self.func, *self.args, **self.kwds) + return self.__class__(self.func, self.args, self.kwds) def __enter__(self): try: @@ -123,7 +123,7 @@ def contextmanager(func): """ @wraps(func) def helper(*args, **kwds): - return _GeneratorContextManager(func, *args, **kwds) + return _GeneratorContextManager(func, args, kwds) return helper diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py index 39cc776dbca..8f849ae5604 100644 --- a/Lib/test/test_contextlib.py +++ b/Lib/test/test_contextlib.py @@ -111,6 +111,14 @@ class ContextManagerTestCase(unittest.TestCase): baz = self._create_contextmanager_attribs()(None) self.assertEqual(baz.__doc__, "Whee!") + def test_keywords(self): + # Ensure no keyword arguments are inhibited + @contextmanager + def woohoo(self, func, args, kwds): + yield (self, func, args, kwds) + with woohoo(self=11, func=22, args=33, kwds=44) as target: + self.assertEqual(target, (11, 22, 33, 44)) + class ClosingTestCase(unittest.TestCase): diff --git a/Lib/test/test_with.py b/Lib/test/test_with.py index 7068a809702..cbaafcf9230 100644 --- a/Lib/test/test_with.py +++ b/Lib/test/test_with.py @@ -12,8 +12,8 @@ from test.support import run_unittest class MockContextManager(_GeneratorContextManager): - def __init__(self, func, *args, **kwds): - super().__init__(func, *args, **kwds) + def __init__(self, *args): + super().__init__(*args) self.enter_called = False self.exit_called = False self.exit_args = None @@ -31,7 +31,7 @@ class MockContextManager(_GeneratorContextManager): def mock_contextmanager(func): def helper(*args, **kwds): - return MockContextManager(func, *args, **kwds) + return MockContextManager(func, args, kwds) return helper diff --git a/Misc/NEWS b/Misc/NEWS index c8c455c9774..02b129a5083 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -60,6 +60,9 @@ Core and Builtins Library ------- +- Issue #24336: The contextmanager decorator now works with functions with + keyword arguments called "func" and "self". Patch by Martin Panter. + - Issue #24489: ensure a previously set C errno doesn't disturb cmath.polar(). - Issue #5633: Fixed timeit when the statement is a string and the setup is not.