]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Don't report deleted attributes in __dir__ (GHGH-10148)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Thu, 6 Jun 2019 10:39:30 +0000 (03:39 -0700)
committerGitHub <noreply@github.com>
Thu, 6 Jun 2019 10:39:30 +0000 (03:39 -0700)
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).
(cherry picked from commit 0df635c7f8aa69e56a092bd4f142f0f164741ab2)

Co-authored-by: Mario Corchero <mariocj89@gmail.com>
Lib/unittest/mock.py
Lib/unittest/test/testmock/testmock.py
Misc/NEWS.d/next/Library/2018-10-27-11-54-12.bpo-35082.HDj1nr.rst [new file with mode: 0644]

index 1e577dff2f41b21dd0ebeb32dabab9ad1a38bc59..569a5146c8c12915fa4cefa54083a91fbd9cffc2 100644 (file)
@@ -684,12 +684,14 @@ class NonCallableMock(Base):
         extras = self._mock_methods or []
         from_type = dir(type(self))
         from_dict = list(self.__dict__)
+        from_child_mocks = [
+            m_name for m_name, m_value in self._mock_children.items()
+            if m_value is not _deleted]
 
         from_type = [e for e in from_type if not e.startswith('_')]
         from_dict = [e for e in from_dict if not e.startswith('_') or
                      _is_magic(e)]
-        return sorted(set(extras + from_type + from_dict +
-                          list(self._mock_children)))
+        return sorted(set(extras + from_type + from_dict + from_child_mocks))
 
 
     def __setattr__(self, name, value):
index 76a648e57f1207772ff5457ae179233edc41011e..f92b921fe664aaa202ec1c378d6b7318b4208d23 100644 (file)
@@ -870,6 +870,15 @@ class MockTest(unittest.TestCase):
             patcher.stop()
 
 
+    def test_dir_does_not_include_deleted_attributes(self):
+        mock = Mock()
+        mock.child.return_value = 1
+
+        self.assertIn('child', dir(mock))
+        del mock.child
+        self.assertNotIn('child', dir(mock))
+
+
     def test_configure_mock(self):
         mock = Mock(foo='bar')
         self.assertEqual(mock.foo, 'bar')
diff --git a/Misc/NEWS.d/next/Library/2018-10-27-11-54-12.bpo-35082.HDj1nr.rst b/Misc/NEWS.d/next/Library/2018-10-27-11-54-12.bpo-35082.HDj1nr.rst
new file mode 100644 (file)
index 0000000..45a0729
--- /dev/null
@@ -0,0 +1,2 @@
+Don't return deleted attributes when calling dir on a
+:class:`unittest.mock.Mock`.