Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions Lib/unittest/mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -728,11 +728,10 @@ def __delattr__(self, name):
# not set on the instance itself
return

if name in self.__dict__:
object.__delattr__(self, name)

obj = self._mock_children.get(name, _missing)
if obj is _deleted:
if name in self.__dict__:
super().__delattr__(name)
elif obj is _deleted:
raise AttributeError(name)
if obj is not _missing:
del self._mock_children[name]
Expand Down
27 changes: 27 additions & 0 deletions Lib/unittest/test/testmock/testmock.py
Original file line number Diff line number Diff line change
Expand Up @@ -1739,6 +1739,33 @@ def test_attribute_deletion(self):
self.assertRaises(AttributeError, getattr, mock, 'f')


def test_mock_does_not_raise_on_repeated_attribute_deletion(self):
# bpo-20239: Assigning and deleting twice an attribute raises.
for mock in (Mock(), MagicMock(), NonCallableMagicMock(),
NonCallableMock()):
mock.foo = 3
self.assertTrue(hasattr(mock, 'foo'))
self.assertEqual(mock.foo, 3)

del mock.foo
self.assertFalse(hasattr(mock, 'foo'))

mock.foo = 4
self.assertTrue(hasattr(mock, 'foo'))
self.assertEqual(mock.foo, 4)

del mock.foo
self.assertFalse(hasattr(mock, 'foo'))


def test_mock_raises_when_deleting_nonexistent_attribute(self):
for mock in (Mock(), MagicMock(), NonCallableMagicMock(),
NonCallableMock()):
del mock.foo
with self.assertRaises(AttributeError):
del mock.foo


def test_reset_mock_does_not_raise_on_attr_deletion(self):
# bpo-31177: reset_mock should not raise AttributeError when attributes
# were deleted in a mock instance
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Allow repeated assignment deletion of :class:`unittest.mock.Mock` attributes.
Patch by Pablo Galindo.