From ad4319975b8eb21f42ed5eaef8ff40d065ff4efc Mon Sep 17 00:00:00 2001 From: xtreak Date: Wed, 20 Mar 2019 17:05:22 +0530 Subject: [PATCH 1/3] Return None on stopping unstarted patch object --- Lib/unittest/mock.py | 2 +- Lib/unittest/test/testmock/testpatch.py | 12 ++++++++++-- .../Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst | 3 +++ 3 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 2ccf0d82ce23bd2..f7085c17ff4e14f 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -1398,7 +1398,7 @@ def __enter__(self): def __exit__(self, *exc_info): """Undo the patch.""" if not _is_started(self): - raise RuntimeError('stop called on unstarted patcher') + return if self.is_local and self.temp_original is not DEFAULT: setattr(self.target, self.attribute, self.temp_original) diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index c484adb605086a5..2975b818355389c 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -772,10 +772,18 @@ def test_patch_start_stop(self): def test_stop_without_start(self): + # bpo-36366: calling stop without start will return None patcher = patch(foo_name, 'bar', 3) + self.assertIsNone(patcher.stop()) - # calling stop without start used to produce a very obscure error - self.assertRaises(RuntimeError, patcher.stop) + + def test_stop_double_stop(self): + # bpo-36366: calling stop on an already stopped patch will return None + patcher = patch(foo_name, 'bar', 3) + + patcher.start() + patcher.stop() + self.assertIsNone(patcher.stop()) def test_patchobject_start_stop(self): diff --git a/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst b/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst new file mode 100644 index 000000000000000..e66b98bb3230022 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst @@ -0,0 +1,3 @@ +Calling ``stop`` on an unstarted or stopped :func:`unittest.mock.patch` +object will not raise :exc:`RuntimeError` and returns `None`. Patch by +Karthikeyan Singaravelan. From b293c59b08ea8e690128d5ac03f3c5da4ea9284e Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Wed, 27 Mar 2019 12:08:41 -0700 Subject: [PATCH 2/3] Touch-up news entry --- .../next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst b/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst index e66b98bb3230022..a43504839c6fffc 100644 --- a/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst +++ b/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst @@ -1,3 +1,4 @@ -Calling ``stop`` on an unstarted or stopped :func:`unittest.mock.patch` -object will not raise :exc:`RuntimeError` and returns `None`. Patch by -Karthikeyan Singaravelan. +Calling ``stop()`` on an unstarted or stopped :func:`unittest.mock.patch` +object will now return `None` instead of raising :exc:`RuntimeError`, +making the method idempotent. +Patch byKarthikeyan Singaravelan. From ecdd40f1fbc952ef1441c566bf9da8cb7dc4c16a Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Thu, 28 Mar 2019 04:47:45 +0530 Subject: [PATCH 3/3] Use better test name and add period to comments. Co-Authored-By: tirkarthi --- Lib/unittest/test/testmock/testpatch.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index 2975b818355389c..2c14360b2df530f 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -772,13 +772,13 @@ def test_patch_start_stop(self): def test_stop_without_start(self): - # bpo-36366: calling stop without start will return None + # bpo-36366: calling stop without start will return None. patcher = patch(foo_name, 'bar', 3) self.assertIsNone(patcher.stop()) - def test_stop_double_stop(self): - # bpo-36366: calling stop on an already stopped patch will return None + def test_stop_idempotent(self): + # bpo-36366: calling stop on an already stopped patch will return None. patcher = patch(foo_name, 'bar', 3) patcher.start()