Skip to content

Commit

Permalink
Closes Issue 21238: New keyword argument unsafe to Mock.
Browse files Browse the repository at this point in the history
It raises `AttributeError` incase of an attribute startswith assert
or assret.
  • Loading branch information
kushaldas committed Apr 16, 2014
1 parent 2a2946c commit 9cff6dd
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 3 deletions.
8 changes: 7 additions & 1 deletion Doc/library/unittest.mock.rst
Expand Up @@ -198,7 +198,7 @@ a `MagicMock` for you. You can specify an alternative class of `Mock` using
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
that specify the behaviour of the Mock object:
Expand Down Expand Up @@ -235,6 +235,12 @@ the `new_callable` argument to `patch`.
this is a new Mock (created on first access). See the
: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
calling the Mock will pass the call through to the wrapped object
(returning the real result). Attribute access on the mock will return a
Expand Down
8 changes: 6 additions & 2 deletions Lib/unittest/mock.py
Expand Up @@ -379,7 +379,7 @@ def __new__(cls, *args, **kw):
def __init__(
self, spec=None, wraps=None, name=None, spec_set=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:
_new_parent = parent
Expand Down Expand Up @@ -409,6 +409,7 @@ def __init__(
__dict__['_mock_mock_calls'] = _CallList()

__dict__['method_calls'] = _CallList()
__dict__['_mock_unsafe'] = unsafe

if kwargs:
self.configure_mock(**kwargs)
Expand Down Expand Up @@ -565,13 +566,16 @@ def configure_mock(self, **kwargs):


def __getattr__(self, name):
if name == '_mock_methods':
if name in {'_mock_methods', '_mock_unsafe'}:
raise AttributeError(name)
elif self._mock_methods is not None:
if name not in self._mock_methods or name in _all_magics:
raise AttributeError("Mock object has no attribute %r" % name)
elif _is_magic(name):
raise AttributeError(name)
if not self._mock_unsafe:
if name.startswith(('assert', 'assret')):
raise AttributeError(name)

result = self._mock_children.get(name)
if result is _deleted:
Expand Down
11 changes: 11 additions & 0 deletions Lib/unittest/test/testmock/testmock.py
Expand Up @@ -1187,6 +1187,17 @@ def test_create_autospec_with_name(self):
m = mock.create_autospec(object(), name='sweet_func')
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):
class _One(object):
one = 1
Expand Down
3 changes: 3 additions & 0 deletions Misc/NEWS
Expand Up @@ -50,6 +50,9 @@ Core and Builtins
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
PROTOCOL_SSLv3, for maximum compatibility.

Expand Down

0 comments on commit 9cff6dd

Please sign in to comment.