Closes Issue 21238: New keyword argument `unsafe` to Mock.
It raises `AttributeError` incase of an attribute startswith assert or assret.
This commit is contained in:
parent
c3ac9af6d0
commit
8c14534df6
|
@ -198,7 +198,7 @@ a `MagicMock` for you. You can specify an alternative class of `Mock` using
|
||||||
the `new_callable` argument to `patch`.
|
the `new_callable` argument to `patch`.
|
||||||
|
|
||||||
|
|
||||||
.. class:: Mock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, **kwargs)
|
.. class:: Mock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, unsafe=False, **kwargs)
|
||||||
|
|
||||||
Create a new `Mock` object. `Mock` takes several optional arguments
|
Create a new `Mock` object. `Mock` takes several optional arguments
|
||||||
that specify the behaviour of the Mock object:
|
that specify the behaviour of the Mock object:
|
||||||
|
@ -235,6 +235,12 @@ the `new_callable` argument to `patch`.
|
||||||
this is a new Mock (created on first access). See the
|
this is a new Mock (created on first access). See the
|
||||||
:attr:`return_value` attribute.
|
:attr:`return_value` attribute.
|
||||||
|
|
||||||
|
* `unsafe`: By default if any attribute starts with *assert* or
|
||||||
|
*assret* will raise an `AttributeError`. Passing `unsafe=True` will allow
|
||||||
|
access to these attributes.
|
||||||
|
|
||||||
|
.. versionadded:: 3.5
|
||||||
|
|
||||||
* `wraps`: Item for the mock object to wrap. If `wraps` is not None then
|
* `wraps`: Item for the mock object to wrap. If `wraps` is not None then
|
||||||
calling the Mock will pass the call through to the wrapped object
|
calling the Mock will pass the call through to the wrapped object
|
||||||
(returning the real result). Attribute access on the mock will return a
|
(returning the real result). Attribute access on the mock will return a
|
||||||
|
|
|
@ -379,7 +379,7 @@ class NonCallableMock(Base):
|
||||||
def __init__(
|
def __init__(
|
||||||
self, spec=None, wraps=None, name=None, spec_set=None,
|
self, spec=None, wraps=None, name=None, spec_set=None,
|
||||||
parent=None, _spec_state=None, _new_name='', _new_parent=None,
|
parent=None, _spec_state=None, _new_name='', _new_parent=None,
|
||||||
_spec_as_instance=False, _eat_self=None, **kwargs
|
_spec_as_instance=False, _eat_self=None, unsafe=False, **kwargs
|
||||||
):
|
):
|
||||||
if _new_parent is None:
|
if _new_parent is None:
|
||||||
_new_parent = parent
|
_new_parent = parent
|
||||||
|
@ -409,6 +409,7 @@ class NonCallableMock(Base):
|
||||||
__dict__['_mock_mock_calls'] = _CallList()
|
__dict__['_mock_mock_calls'] = _CallList()
|
||||||
|
|
||||||
__dict__['method_calls'] = _CallList()
|
__dict__['method_calls'] = _CallList()
|
||||||
|
__dict__['_mock_unsafe'] = unsafe
|
||||||
|
|
||||||
if kwargs:
|
if kwargs:
|
||||||
self.configure_mock(**kwargs)
|
self.configure_mock(**kwargs)
|
||||||
|
@ -565,13 +566,16 @@ class NonCallableMock(Base):
|
||||||
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name == '_mock_methods':
|
if name in {'_mock_methods', '_mock_unsafe'}:
|
||||||
raise AttributeError(name)
|
raise AttributeError(name)
|
||||||
elif self._mock_methods is not None:
|
elif self._mock_methods is not None:
|
||||||
if name not in self._mock_methods or name in _all_magics:
|
if name not in self._mock_methods or name in _all_magics:
|
||||||
raise AttributeError("Mock object has no attribute %r" % name)
|
raise AttributeError("Mock object has no attribute %r" % name)
|
||||||
elif _is_magic(name):
|
elif _is_magic(name):
|
||||||
raise AttributeError(name)
|
raise AttributeError(name)
|
||||||
|
if not self._mock_unsafe:
|
||||||
|
if name.startswith(('assert', 'assret')):
|
||||||
|
raise AttributeError(name)
|
||||||
|
|
||||||
result = self._mock_children.get(name)
|
result = self._mock_children.get(name)
|
||||||
if result is _deleted:
|
if result is _deleted:
|
||||||
|
|
|
@ -1187,6 +1187,17 @@ class MockTest(unittest.TestCase):
|
||||||
m = mock.create_autospec(object(), name='sweet_func')
|
m = mock.create_autospec(object(), name='sweet_func')
|
||||||
self.assertIn('sweet_func', repr(m))
|
self.assertIn('sweet_func', repr(m))
|
||||||
|
|
||||||
|
#Issue21238
|
||||||
|
def test_mock_unsafe(self):
|
||||||
|
m = Mock()
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
m.assert_foo_call()
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
m.assret_foo_call()
|
||||||
|
m = Mock(unsafe=True)
|
||||||
|
m.assert_foo_call()
|
||||||
|
m.assret_foo_call()
|
||||||
|
|
||||||
def test_mock_add_spec(self):
|
def test_mock_add_spec(self):
|
||||||
class _One(object):
|
class _One(object):
|
||||||
one = 1
|
one = 1
|
||||||
|
|
|
@ -50,6 +50,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #21238: New keyword argument `unsafe` to Mock. It raises
|
||||||
|
`AttributeError` incase of an attribute startswith assert or assret.
|
||||||
|
|
||||||
- Issue #20896: ssl.get_server_certificate() now uses PROTOCOL_SSLv23, not
|
- Issue #20896: ssl.get_server_certificate() now uses PROTOCOL_SSLv23, not
|
||||||
PROTOCOL_SSLv3, for maximum compatibility.
|
PROTOCOL_SSLv3, for maximum compatibility.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue