[Python-checkins] cpython: Make unittest.mock.create_autospec resilient against AttributeError on original

michael.foord python-checkins at python.org
Fri Apr 13 18:39:34 CEST 2012


http://hg.python.org/cpython/rev/1f841cb8e056
changeset:   76288:1f841cb8e056
parent:      76286:4d1349013dd4
user:        Michael Foord <michael at voidspace.org.uk>
date:        Fri Apr 13 17:39:16 2012 +0100
summary:
  Make unittest.mock.create_autospec resilient against AttributeError on original object

files:
  Lib/unittest/mock.py                      |   8 ++-
  Lib/unittest/test/testmock/testhelpers.py |  23 +++++++++++
  2 files changed, 29 insertions(+), 2 deletions(-)


diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -2044,10 +2044,14 @@
         # object to mock it so we would rather trigger a property than mock
         # the property descriptor. Likewise we want to mock out dynamically
         # provided attributes.
-        # XXXX what about attributes that raise exceptions on being fetched
+        # XXXX what about attributes that raise exceptions other than
+        # AttributeError on being fetched?
         # we could be resilient against it, or catch and propagate the
         # exception when the attribute is fetched from the mock
-        original = getattr(spec, entry)
+        try:
+            original = getattr(spec, entry)
+        except AttributeError:
+            continue
 
         kwargs = {'spec': original}
         if spec_set:
diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py
--- a/Lib/unittest/test/testmock/testhelpers.py
+++ b/Lib/unittest/test/testmock/testhelpers.py
@@ -651,6 +651,29 @@
         mock.f.assert_called_with(3, 4)
 
 
+    def test_skip_attributeerrors(self):
+        class Raiser(object):
+            def __get__(self, obj, type=None):
+                if obj is None:
+                    raise AttributeError('Can only be accessed via an instance')
+
+        class RaiserClass(object):
+            raiser = Raiser()
+
+            @staticmethod
+            def existing(a, b):
+                return a + b
+
+        s = create_autospec(RaiserClass)
+        self.assertRaises(TypeError, lambda x: s.existing(1, 2, 3))
+        s.existing(1, 2)
+        self.assertRaises(AttributeError, lambda: s.nonexisting)
+
+        # check we can fetch the raiser attribute and it has no spec
+        obj = s.raiser
+        obj.foo, obj.bar
+
+
     def test_signature_class(self):
         class Foo(object):
             def __init__(self, a, b=3):

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list