mirror of https://github.com/python/cpython
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.
This commit is contained in:
commit
d0d24fd1ae
|
@ -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 = {}
|
||||
|
|
|
@ -802,35 +802,53 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
a.f.assert_called_with(self=10)
|
||||
|
||||
|
||||
def test_autospec_property(self):
|
||||
def test_autospec_data_descriptor(self):
|
||||
class Descriptor(object):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __get__(self, obj, cls=None):
|
||||
if obj is None:
|
||||
return self
|
||||
return self.value
|
||||
|
||||
def __set__(self, obj, value):
|
||||
pass
|
||||
|
||||
class MyProperty(property):
|
||||
pass
|
||||
|
||||
class Foo(object):
|
||||
__slots__ = ['slot']
|
||||
|
||||
@property
|
||||
def foo(self):
|
||||
def prop(self):
|
||||
return 3
|
||||
|
||||
foo = create_autospec(Foo)
|
||||
mock_property = foo.foo
|
||||
@MyProperty
|
||||
def subprop(self):
|
||||
return 4
|
||||
|
||||
# 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 test_autospec_slots(self):
|
||||
class Foo(object):
|
||||
__slots__ = ['a']
|
||||
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):
|
||||
|
|
|
@ -43,6 +43,10 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- 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.
|
||||
|
||||
- Issue #26754: Undocumented support of general bytes-like objects
|
||||
as path in compile() and similar functions is now deprecated.
|
||||
|
||||
|
|
Loading…
Reference in New Issue