80 lines
2.5 KiB
Diff
80 lines
2.5 KiB
Diff
|
From c0dea0309b9a0a7cbc87727c9957f0a388fb9b0f Mon Sep 17 00:00:00 2001
|
||
|
From: Nikita Sobolev <mail@sobolevn.me>
|
||
|
Date: Fri, 11 Nov 2022 11:04:30 +0300
|
||
|
Subject: [PATCH] gh-98086: Now ``patch.dict`` can decorate async functions
|
||
|
(GH-98095) (cherry picked from commit
|
||
|
67b4d2772c5124b908f8ed9b13166a79bbeb88d2)
|
||
|
|
||
|
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
|
||
|
---
|
||
|
Lib/unittest/mock.py | 18 ++++++++++
|
||
|
Lib/unittest/test/testmock/testasync.py | 17 +++++++++
|
||
|
Misc/NEWS.d/next/Library/2022-10-08-19-39-27.gh-issue-98086.y---WC.rst | 1
|
||
|
3 files changed, 36 insertions(+)
|
||
|
create mode 100644 Misc/NEWS.d/next/Library/2022-10-08-19-39-27.gh-issue-98086.y---WC.rst
|
||
|
|
||
|
--- a/Lib/unittest/mock.py
|
||
|
+++ b/Lib/unittest/mock.py
|
||
|
@@ -1761,6 +1761,12 @@ class _patch_dict(object):
|
||
|
def __call__(self, f):
|
||
|
if isinstance(f, type):
|
||
|
return self.decorate_class(f)
|
||
|
+ if inspect.iscoroutinefunction(f):
|
||
|
+ return self.decorate_async_callable(f)
|
||
|
+ return self.decorate_callable(f)
|
||
|
+
|
||
|
+
|
||
|
+ def decorate_callable(self, f):
|
||
|
@wraps(f)
|
||
|
def _inner(*args, **kw):
|
||
|
self._patch_dict()
|
||
|
@@ -1769,6 +1775,18 @@ class _patch_dict(object):
|
||
|
finally:
|
||
|
self._unpatch_dict()
|
||
|
|
||
|
+ return _inner
|
||
|
+
|
||
|
+
|
||
|
+ def decorate_async_callable(self, f):
|
||
|
+ @wraps(f)
|
||
|
+ async def _inner(*args, **kw):
|
||
|
+ self._patch_dict()
|
||
|
+ try:
|
||
|
+ return await f(*args, **kw)
|
||
|
+ finally:
|
||
|
+ self._unpatch_dict()
|
||
|
+
|
||
|
return _inner
|
||
|
|
||
|
|
||
|
--- a/Lib/unittest/test/testmock/testasync.py
|
||
|
+++ b/Lib/unittest/test/testmock/testasync.py
|
||
|
@@ -146,6 +146,23 @@ class AsyncPatchCMTest(unittest.TestCase
|
||
|
|
||
|
run(test_async())
|
||
|
|
||
|
+ def test_patch_dict_async_def(self):
|
||
|
+ foo = {'a': 'a'}
|
||
|
+ @patch.dict(foo, {'a': 'b'})
|
||
|
+ async def test_async():
|
||
|
+ self.assertEqual(foo['a'], 'b')
|
||
|
+
|
||
|
+ self.assertTrue(iscoroutinefunction(test_async))
|
||
|
+ run(test_async())
|
||
|
+
|
||
|
+ def test_patch_dict_async_def_context(self):
|
||
|
+ foo = {'a': 'a'}
|
||
|
+ async def test_async():
|
||
|
+ with patch.dict(foo, {'a': 'b'}):
|
||
|
+ self.assertEqual(foo['a'], 'b')
|
||
|
+
|
||
|
+ run(test_async())
|
||
|
+
|
||
|
|
||
|
class AsyncMockTest(unittest.TestCase):
|
||
|
def test_iscoroutinefunction_default(self):
|
||
|
--- /dev/null
|
||
|
+++ b/Misc/NEWS.d/next/Library/2022-10-08-19-39-27.gh-issue-98086.y---WC.rst
|
||
|
@@ -0,0 +1 @@
|
||
|
+Make sure ``patch.dict()`` can be applied on async functions.
|