Skip to content

[3.7] bpo-35357: Add _mock_ prefix to name/parent/from_kall attributes of _Call/_MagicProxy. (GH-10873) #10887

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions Lib/unittest/mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -2016,9 +2016,9 @@ def __new__(cls, value=(), name='', parent=None, two=False,

def __init__(self, value=(), name=None, parent=None, two=False,
from_kall=True):
self.name = name
self.parent = parent
self.from_kall = from_kall
self._mock_name = name
self._mock_parent = parent
self._mock_from_kall = from_kall


def __eq__(self, other):
Expand All @@ -2035,8 +2035,8 @@ def __eq__(self, other):
else:
self_name, self_args, self_kwargs = self

if (getattr(self, 'parent', None) and getattr(other, 'parent', None)
and self.parent != other.parent):
if (getattr(self, '_mock_parent', None) and getattr(other, '_mock_parent', None)
and self._mock_parent != other._mock_parent):
return False

other_name = ''
Expand Down Expand Up @@ -2080,17 +2080,17 @@ def __eq__(self, other):


def __call__(self, *args, **kwargs):
if self.name is None:
if self._mock_name is None:
return _Call(('', args, kwargs), name='()')

name = self.name + '()'
return _Call((self.name, args, kwargs), name=name, parent=self)
name = self._mock_name + '()'
return _Call((self._mock_name, args, kwargs), name=name, parent=self)


def __getattr__(self, attr):
if self.name is None:
if self._mock_name is None:
return _Call(name=attr, from_kall=False)
name = '%s.%s' % (self.name, attr)
name = '%s.%s' % (self._mock_name, attr)
return _Call(name=name, parent=self, from_kall=False)


Expand All @@ -2101,8 +2101,8 @@ def index(self, *args, **kwargs):
return self.__getattr__('index')(*args, **kwargs)

def __repr__(self):
if not self.from_kall:
name = self.name or 'call'
if not self._mock_from_kall:
name = self._mock_name or 'call'
if name.startswith('()'):
name = 'call%s' % name
return name
Expand All @@ -2128,9 +2128,9 @@ def call_list(self):
vals = []
thing = self
while thing is not None:
if thing.from_kall:
if thing._mock_from_kall:
vals.append(thing)
thing = thing.parent
thing = thing._mock_parent
return _CallList(reversed(vals))


Expand Down
2 changes: 1 addition & 1 deletion Lib/unittest/test/testmock/testcallable.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class Multi(SomeClass, Sub):
result.foo.assert_called_once_with(3, 2, 1)


def test_create_autopsec(self):
def test_create_autospec(self):
mock = create_autospec(X)
instance = mock()
self.assertRaises(TypeError, instance)
Expand Down
16 changes: 15 additions & 1 deletion Lib/unittest/test/testmock/testmock.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from unittest.mock import (
call, DEFAULT, patch, sentinel,
MagicMock, Mock, NonCallableMock,
NonCallableMagicMock, _CallList,
NonCallableMagicMock, _Call, _CallList,
create_autospec
)

Expand Down Expand Up @@ -1635,6 +1635,20 @@ def test_class_assignable(self):
self.assertIsInstance(mock, int)
mock.foo

def test_name_attribute_of_call(self):
# bpo-35357: _Call should not disclose any attributes whose names
# may clash with popular ones (such as ".name")
self.assertIsNotNone(call.name)
self.assertEqual(type(call.name), _Call)
self.assertEqual(type(call.name().name), _Call)

def test_parent_attribute_of_call(self):
# bpo-35357: _Call should not disclose any attributes whose names
# may clash with popular ones (such as ".parent")
self.assertIsNotNone(call.parent)
self.assertEqual(type(call.parent), _Call)
self.assertEqual(type(call.parent().parent), _Call)


if __name__ == '__main__':
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Internal attributes' names of unittest.mock._Call and
unittest.mock.MagicProxy (name, parent & from_kall) are now prefixed with
_mock_ in order to prevent clashes with widely used object attributes.
Fixed minor typo in test function name.