mirror of
https://github.com/python/cpython.git
synced 2026-01-06 07:22:09 +00:00
gh-100690: Raise an AttributeError when the assert_ prefix is forgotten when using Mock (#100691)
Mock objects which are not unsafe will now raise an AttributeError when accessing an attribute that matches the name of an assertion but without the prefix `assert_`, e.g. accessing `called_once` instead of `assert_called_once`. This is in addition to this already happening for accessing attributes with prefixes assert, assret, asert, aseert, and assrt.
This commit is contained in:
parent
9ffbc58f5c
commit
1d4d677d1c
3 changed files with 41 additions and 4 deletions
|
|
@ -1645,12 +1645,36 @@ def test_mock_unsafe(self):
|
|||
m.aseert_foo_call()
|
||||
with self.assertRaisesRegex(AttributeError, msg):
|
||||
m.assrt_foo_call()
|
||||
with self.assertRaisesRegex(AttributeError, msg):
|
||||
m.called_once_with()
|
||||
with self.assertRaisesRegex(AttributeError, msg):
|
||||
m.called_once()
|
||||
with self.assertRaisesRegex(AttributeError, msg):
|
||||
m.has_calls()
|
||||
|
||||
class Foo(object):
|
||||
def called_once(self):
|
||||
pass
|
||||
|
||||
def has_calls(self):
|
||||
pass
|
||||
|
||||
m = Mock(spec=Foo)
|
||||
m.called_once()
|
||||
m.has_calls()
|
||||
|
||||
m.called_once.assert_called_once()
|
||||
m.has_calls.assert_called_once()
|
||||
|
||||
m = Mock(unsafe=True)
|
||||
m.assert_foo_call()
|
||||
m.assret_foo_call()
|
||||
m.asert_foo_call()
|
||||
m.aseert_foo_call()
|
||||
m.assrt_foo_call()
|
||||
m.called_once()
|
||||
m.called_once_with()
|
||||
m.has_calls()
|
||||
|
||||
# gh-100739
|
||||
def test_mock_safe_with_spec(self):
|
||||
|
|
|
|||
|
|
@ -653,7 +653,7 @@ def __getattr__(self, name):
|
|||
elif _is_magic(name):
|
||||
raise AttributeError(name)
|
||||
if not self._mock_unsafe and (not self._mock_methods or name not in self._mock_methods):
|
||||
if name.startswith(('assert', 'assret', 'asert', 'aseert', 'assrt')):
|
||||
if name.startswith(('assert', 'assret', 'asert', 'aseert', 'assrt')) or name in ATTRIB_DENY_LIST:
|
||||
raise AttributeError(
|
||||
f"{name!r} is not a valid assertion. Use a spec "
|
||||
f"for the mock if {name!r} is meant to be an attribute.")
|
||||
|
|
@ -1062,6 +1062,10 @@ def _calls_repr(self, prefix="Calls"):
|
|||
return f"\n{prefix}: {safe_repr(self.mock_calls)}."
|
||||
|
||||
|
||||
# Denylist for forbidden attribute names in safe mode
|
||||
ATTRIB_DENY_LIST = {name.removeprefix("assert_") for name in dir(NonCallableMock) if name.startswith("assert_")}
|
||||
|
||||
|
||||
class _AnyComparer(list):
|
||||
"""A list which checks if it contains a call which may have an
|
||||
argument of ANY, flipping the components of item and self from
|
||||
|
|
@ -1231,9 +1235,11 @@ class or instance) that acts as the specification for the mock object. If
|
|||
`return_value` attribute.
|
||||
|
||||
* `unsafe`: By default, accessing any attribute whose name starts with
|
||||
*assert*, *assret*, *asert*, *aseert* or *assrt* will raise an
|
||||
AttributeError. Passing `unsafe=True` will allow access to
|
||||
these attributes.
|
||||
*assert*, *assret*, *asert*, *aseert*, or *assrt* raises an AttributeError.
|
||||
Additionally, an AttributeError is raised when accessing
|
||||
attributes that match the name of an assertion method without the prefix
|
||||
`assert_`, e.g. accessing `called_once` instead of `assert_called_once`.
|
||||
Passing `unsafe=True` will allow access to these attributes.
|
||||
|
||||
* `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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
``Mock`` objects which are not unsafe will now raise an
|
||||
``AttributeError`` when accessing an attribute that matches the name
|
||||
of an assertion but without the prefix ``assert_``, e.g. accessing
|
||||
``called_once`` instead of ``assert_called_once``.
|
||||
This is in addition to this already happening for accessing attributes
|
||||
with prefixes ``assert``, ``assret``, ``asert``, ``aseert``,
|
||||
and ``assrt``.
|
||||
Loading…
Add table
Add a link
Reference in a new issue