summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorGregory P. Smith <greg@krypto.org>2016-08-07 16:06:27 (GMT)
committerGregory P. Smith <greg@krypto.org>2016-08-07 16:06:27 (GMT)
commitd0d24fd1ae05a2aea84165cf0aae98f75a5203c8 (patch)
tree79cc2f86abbeb40149b52c3c2da4798387d57bb7 /Lib
parent3cc38327b636e81b079edb0fd206ec678276e83f (diff)
parent9854789efec0c707fff871b32b2833f32b078fb3 (diff)
downloadcpython-d0d24fd1ae05a2aea84165cf0aae98f75a5203c8.zip
cpython-d0d24fd1ae05a2aea84165cf0aae98f75a5203c8.tar.gz
cpython-d0d24fd1ae05a2aea84165cf0aae98f75a5203c8.tar.bz2
Issue #26750: unittest.mock.create_autospec() now works properly for
subclasses of property() and other data descriptors. Removes the never publicly used, never documented unittest.mock.DescriptorTypes tuple.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/unittest/mock.py14
-rw-r--r--Lib/unittest/test/testmock/testhelpers.py60
2 files changed, 44 insertions, 30 deletions
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index 4f91c44..ed915d2 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -60,14 +60,10 @@ def _is_exception(obj):
)
-class _slotted(object):
- __slots__ = ['a']
-
-
-DescriptorTypes = (
- type(_slotted.a),
- property,
-)
+def _is_data_descriptor(obj):
+ # Data descriptors are Properties, slots, getsets and C data members.
+ return ((hasattr(obj, '__set__') or hasattr(obj, '__del__')) and
+ hasattr(obj, '__get__'))
def _get_signature_object(func, as_instance, eat_self):
@@ -2153,7 +2149,7 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
_kwargs.update(kwargs)
Klass = MagicMock
- if type(spec) in DescriptorTypes:
+ if _is_data_descriptor(spec):
# descriptors don't have a spec
# because we don't know what type they return
_kwargs = {}
diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py
index 1dbc0b6..3477634 100644
--- a/Lib/unittest/test/testmock/testhelpers.py
+++ b/Lib/unittest/test/testmock/testhelpers.py
@@ -802,35 +802,53 @@ class SpecSignatureTest(unittest.TestCase):
a.f.assert_called_with(self=10)
- def test_autospec_property(self):
- class Foo(object):
- @property
- def foo(self):
- return 3
+ def test_autospec_data_descriptor(self):
+ class Descriptor(object):
+ def __init__(self, value):
+ self.value = value
- foo = create_autospec(Foo)
- mock_property = foo.foo
+ def __get__(self, obj, cls=None):
+ if obj is None:
+ return self
+ return self.value
- # no spec on properties
- self.assertIsInstance(mock_property, MagicMock)
- mock_property(1, 2, 3)
- mock_property.abc(4, 5, 6)
- mock_property.assert_called_once_with(1, 2, 3)
- mock_property.abc.assert_called_once_with(4, 5, 6)
+ def __set__(self, obj, value):
+ pass
+ class MyProperty(property):
+ pass
- def test_autospec_slots(self):
class Foo(object):
- __slots__ = ['a']
+ __slots__ = ['slot']
+
+ @property
+ def prop(self):
+ return 3
+
+ @MyProperty
+ def subprop(self):
+ return 4
+
+ desc = Descriptor(42)
foo = create_autospec(Foo)
- mock_slot = foo.a
- # no spec on slots
- mock_slot(1, 2, 3)
- mock_slot.abc(4, 5, 6)
- mock_slot.assert_called_once_with(1, 2, 3)
- mock_slot.abc.assert_called_once_with(4, 5, 6)
+ def check_data_descriptor(mock_attr):
+ # Data descriptors don't have a spec.
+ self.assertIsInstance(mock_attr, MagicMock)
+ mock_attr(1, 2, 3)
+ mock_attr.abc(4, 5, 6)
+ mock_attr.assert_called_once_with(1, 2, 3)
+ mock_attr.abc.assert_called_once_with(4, 5, 6)
+
+ # property
+ check_data_descriptor(foo.prop)
+ # property subclass
+ check_data_descriptor(foo.subprop)
+ # class __slot__
+ check_data_descriptor(foo.slot)
+ # plain data descriptor
+ check_data_descriptor(foo.desc)
class TestCallList(unittest.TestCase):