Skip to content

Commit e2c8f05

Browse files
committed
Don't report deleted attributes in __dir__
When an attribute is deleted from a Mock, a sentinel is added rather than just deleting the attribute. This commit checks for such sentinels when returning the child mocks in the __dir__ method as users won't expect deleted attributes to appear when performing dir(mock).
1 parent fec35c9 commit e2c8f05

3 files changed

Lines changed: 15 additions & 2 deletions

File tree

Lib/unittest/mock.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -671,12 +671,14 @@ def __dir__(self):
671671
extras = self._mock_methods or []
672672
from_type = dir(type(self))
673673
from_dict = list(self.__dict__)
674+
from_child_mocks = [
675+
m_name for m_name, m_value in self._mock_children.items()
676+
if m_value is not _deleted]
674677

675678
from_type = [e for e in from_type if not e.startswith('_')]
676679
from_dict = [e for e in from_dict if not e.startswith('_') or
677680
_is_magic(e)]
678-
return sorted(set(extras + from_type + from_dict +
679-
list(self._mock_children)))
681+
return sorted(set(extras + from_type + from_dict + from_child_mocks))
680682

681683

682684
def __setattr__(self, name, value):

Lib/unittest/test/testmock/testmock.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,15 @@ def test_filter_dir(self):
748748
patcher.stop()
749749

750750

751+
def test_dir_does_not_include_deleted_attributes(self):
752+
mock = Mock()
753+
mock.child.return_value = 1
754+
755+
self.assertIn('child', dir(mock))
756+
del mock.child
757+
self.assertNotIn('child', dir(mock))
758+
759+
751760
def test_configure_mock(self):
752761
mock = Mock(foo='bar')
753762
self.assertEqual(mock.foo, 'bar')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Don't return deleted attributes when calling dir on a
2+
:class:`unittest.mock.Mock`.

0 commit comments

Comments
 (0)