diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 9f99a5aa5bcdcb..ff5ae392ccf6da 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -494,6 +494,10 @@ def _mock_add_spec(self, spec, spec_set, _spec_as_instance=False, _spec_asyncs = [] for attr in dir(spec): + if isinstance(inspect.getattr_static(spec, attr, None), property): + # Don't execute `property` decorators with `getattr`. + # It might affect user's code in unknown way. + continue if iscoroutinefunction(getattr(spec, attr, None)): _spec_asyncs.append(attr) diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py index fdba543b53511d..d76d83f1717773 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -896,6 +896,36 @@ def set_attr(): self.assertRaises(AttributeError, set_attr) + def test_class_with_property(self): + class X: + @property + def some(self): + raise ValueError('Should not be raised') + + mock = Mock(spec=X) + self.assertIsInstance(mock, X) + + mock = Mock(spec=X()) + self.assertIsInstance(mock, X) + + + def test_class_with_settable_property(self): + class X: + @property + def some(self): + raise ValueError('Should not be raised') + + @some.setter + def some(self, value): + raise TypeError('Should not be raised') + + mock = Mock(spec=X) + self.assertIsInstance(mock, X) + + mock = Mock(spec=X()) + self.assertIsInstance(mock, X) + + def test_copy(self): current = sys.getrecursionlimit() self.addCleanup(sys.setrecursionlimit, current) diff --git a/Misc/NEWS.d/next/Library/2021-12-03-11-19-44.bpo-45756.nSDJWj.rst b/Misc/NEWS.d/next/Library/2021-12-03-11-19-44.bpo-45756.nSDJWj.rst new file mode 100644 index 00000000000000..36e2ca4b56c150 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-03-11-19-44.bpo-45756.nSDJWj.rst @@ -0,0 +1,2 @@ +Do not execute ``@property`` descriptors while creating autospecs in :mod:`unittest.mock`. +This was not safe and could affect users' code in unknown way.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: