From ac38571f00ccb5e1e0346ad27a8fac96d05e61c3 Mon Sep 17 00:00:00 2001 From: Richard Oudkerk Date: Mon, 18 Jun 2012 21:29:30 +0100 Subject: [PATCH] Issue #15064: Make BaseManager.__enter__() start server if necessary. --- Doc/library/multiprocessing.rst | 11 ++++++++--- Lib/multiprocessing/managers.py | 3 +++ Lib/test/test_multiprocessing.py | 26 ++++++++++++++++++++------ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index 2f64bb1f927..885885915b8 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -1281,9 +1281,14 @@ their parent process exits. The manager classes are defined in the The address used by the manager. - Manager objects support the context manager protocol -- see - :ref:`typecontextmanager`. :meth:`__enter__` returns the - manager object, and :meth:`__exit__` calls :meth:`shutdown`. + .. versionchanged:: 3.3 + Manager objects support the context manager protocol -- see + :ref:`typecontextmanager`. :meth:`__enter__` starts the server + process (if it has not already started) and then returns the + manager object. :meth:`__exit__` calls :meth:`shutdown`. + + In previous versions :meth:`__enter__` did not start the + manager's server process if it was not already started. .. class:: SyncManager diff --git a/Lib/multiprocessing/managers.py b/Lib/multiprocessing/managers.py index f6611af9a6c..1ab147e29e6 100644 --- a/Lib/multiprocessing/managers.py +++ b/Lib/multiprocessing/managers.py @@ -561,6 +561,9 @@ def _number_of_objects(self): conn.close() def __enter__(self): + if self._state.value == State.INITIAL: + self.start() + assert self._state.value == State.STARTED return self def __exit__(self, exc_type, exc_val, exc_tb): diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py index 017e6b4796d..f6f4f73952d 100644 --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -1888,7 +1888,27 @@ class _TestMyManager(BaseTestCase): def test_mymanager(self): manager = MyManager() manager.start() + self.common(manager) + manager.shutdown() + # If the manager process exited cleanly then the exitcode + # will be zero. Otherwise (after a short timeout) + # terminate() is used, resulting in an exitcode of -SIGTERM. + self.assertEqual(manager._process.exitcode, 0) + + def test_mymanager_context(self): + with MyManager() as manager: + self.common(manager) + self.assertEqual(manager._process.exitcode, 0) + + def test_mymanager_context_prestarted(self): + manager = MyManager() + manager.start() + with manager: + self.common(manager) + self.assertEqual(manager._process.exitcode, 0) + + def common(self, manager): foo = manager.Foo() bar = manager.Bar() baz = manager.baz() @@ -1911,12 +1931,6 @@ def test_mymanager(self): self.assertEqual(list(baz), [i*i for i in range(10)]) - manager.shutdown() - - # If the manager process exited cleanly then the exitcode - # will be zero. Otherwise (after a short timeout) - # terminate() is used, resulting in an exitcode of -SIGTERM. - self.assertEqual(manager._process.exitcode, 0) # # Test of connecting to a remote server and using xmlrpclib for serialization