From 45a99ec420fa6898e73896cd72b6c7ffe704608b Mon Sep 17 00:00:00 2001 From: hongweipeng Date: Tue, 15 Feb 2022 14:31:18 +0800 Subject: [PATCH 1/2] Fix mock triggers dynamic lookup via the descriptor protocol. --- Lib/unittest/mock.py | 4 ++-- Lib/unittest/test/testmock/testmock.py | 14 ++++++++++++++ .../2022-02-15-14-29-41.bpo-45756.P0sGlU.rst | 2 ++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-02-15-14-29-41.bpo-45756.P0sGlU.rst diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 2719f74d6fca50..f6eed9c7b1852a 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -496,8 +496,8 @@ def _mock_add_spec(self, spec, spec_set, _spec_as_instance=False, _spec_signature = None _spec_asyncs = [] - for attr in dir(spec): - if iscoroutinefunction(getattr(spec, attr, None)): + for attr, value in inspect.getmembers_static(spec): + if iscoroutinefunction(value): _spec_asyncs.append(attr) if spec is not None and not _is_list(spec): diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py index c99098dc4ea86a..aaac55c18d28dd 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -325,6 +325,20 @@ def test_call(self): "call_args_list not set") + def test_not_called_descriptor_protocol(self): + import types + class A: + @property + def name(self): + raise NotImplementedError + @types.DynamicClassAttribute + def eggs(self): + raise NotImplementedError + + self.assertIsInstance(Mock(spec=A), A) + self.assertIsInstance(Mock(spec=A()), A) + + def test_call_args_comparison(self): mock = Mock() mock() diff --git a/Misc/NEWS.d/next/Library/2022-02-15-14-29-41.bpo-45756.P0sGlU.rst b/Misc/NEWS.d/next/Library/2022-02-15-14-29-41.bpo-45756.P0sGlU.rst new file mode 100644 index 00000000000000..92f942ebd0a346 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-02-15-14-29-41.bpo-45756.P0sGlU.rst @@ -0,0 +1,2 @@ +Fix :mod:`unittest.mock` triggers dynamic lookup via the descriptor +protocol. Patch by Weipeng Hong. From e70c22feaa1cd8e4d7dcd97390f573618d134685 Mon Sep 17 00:00:00 2001 From: hongweipeng Date: Tue, 15 Feb 2022 23:11:58 +0800 Subject: [PATCH 2/2] simplify --- Lib/unittest/mock.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index f6eed9c7b1852a..d3ea5a5614c4c7 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -496,9 +496,8 @@ def _mock_add_spec(self, spec, spec_set, _spec_as_instance=False, _spec_signature = None _spec_asyncs = [] - for attr, value in inspect.getmembers_static(spec): - if iscoroutinefunction(value): - _spec_asyncs.append(attr) + for attr, _ in inspect.getmembers_static(spec, iscoroutinefunction): + _spec_asyncs.append(attr) if spec is not None and not _is_list(spec): if isinstance(spec, type):