bpo-45156: Fixes inifite loop on unittest.mock.seal() (GH-28300)

Fixes infinite loop on unittest.mock.seal() of mocks created by
unittest.create_autospec().

Co-authored-by: Dong-hee Na <donghee.na92@gmail.com>
(cherry picked from commit 7f60c9e1c6)

Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
This commit is contained in:
Miss Islington (bot) 2021-09-14 03:50:28 -07:00 committed by GitHub
parent 9cd8fb8d63
commit 13257d9fca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 6 deletions

View file

@ -992,6 +992,11 @@ class NonCallableMock(Base):
if _new_name in self.__dict__['_spec_asyncs']:
return AsyncMock(**kw)
if self._mock_sealed:
attribute = f".{kw['name']}" if "name" in kw else "()"
mock_name = self._extract_mock_name() + attribute
raise AttributeError(mock_name)
_type = type(self)
if issubclass(_type, MagicMock) and _new_name in _async_method_magics:
# Any asynchronous magic becomes an AsyncMock
@ -1010,12 +1015,6 @@ class NonCallableMock(Base):
klass = Mock
else:
klass = _type.__mro__[1]
if self._mock_sealed:
attribute = "." + kw["name"] if "name" in kw else "()"
mock_name = self._extract_mock_name() + attribute
raise AttributeError(mock_name)
return klass(**kw)
@ -2869,6 +2868,8 @@ def seal(mock):
continue
if not isinstance(m, NonCallableMock):
continue
if isinstance(m._mock_children.get(attr), _SpecState):
continue
if m._mock_new_parent is mock:
seal(m)