summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2022-11-20 16:06:57 (GMT)
committerGitHub <noreply@github.com>2022-11-20 16:06:57 (GMT)
commit88b101ff52010f795b34e3afc04c0e934d662d82 (patch)
tree25582945bc12f7ae3871f467386c4f3d8e408da9
parent42b7b2179e27f6df110a1b528fc948784e497265 (diff)
downloadcpython-88b101ff52010f795b34e3afc04c0e934d662d82.zip
cpython-88b101ff52010f795b34e3afc04c0e934d662d82.tar.gz
cpython-88b101ff52010f795b34e3afc04c0e934d662d82.tar.bz2
[3.10] gh-98086: Now ``patch.dict`` can decorate async functions (GH-98095) (GH-99366)
gh-98086: Now ``patch.dict`` can decorate async functions (GH-98095) (cherry picked from commit 67b4d2772c5124b908f8ed9b13166a79bbeb88d2) Co-authored-by: Nikita Sobolev <mail@sobolevn.me> Co-authored-by: Chris Withers <chris@withers.org>
-rw-r--r--Lib/unittest/mock.py18
-rw-r--r--Lib/unittest/test/testmock/testasync.py17
-rw-r--r--Misc/NEWS.d/next/Library/2022-10-08-19-39-27.gh-issue-98086.y---WC.rst1
3 files changed, 36 insertions, 0 deletions
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index b49030a..a647e5d 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -1820,6 +1820,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()
@@ -1831,6 +1837,18 @@ class _patch_dict(object):
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
+
+
def decorate_class(self, klass):
for attr in dir(klass):
attr_value = getattr(klass, attr)
diff --git a/Lib/unittest/test/testmock/testasync.py b/Lib/unittest/test/testmock/testasync.py
index e1866a3..22228b4 100644
--- 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):
diff --git a/Misc/NEWS.d/next/Library/2022-10-08-19-39-27.gh-issue-98086.y---WC.rst b/Misc/NEWS.d/next/Library/2022-10-08-19-39-27.gh-issue-98086.y---WC.rst
new file mode 100644
index 0000000..f4a1d27
--- /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.