python / cpython

The Python programming language
https://www.python.org
Other
62.35k stars 29.94k forks source link

Mock `_mock_wraps` is undocumented and inconsistently named #87439

Open 9c2b5b91-db8b-4482-862f-75ed6f509b3c opened 3 years ago

9c2b5b91-db8b-4482-862f-75ed6f509b3c commented 3 years ago
BPO 43273
Nosy @terryjreedy, @Woodz

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields: ```python assignee = None closed_at = None created_at = labels = ['3.8', 'library'] title = 'Mock `_mock_wraps` is undocumented and inconsistently named' updated_at = user = 'https://github.com/Woodz' ``` bugs.python.org fields: ```python activity = actor = 'terry.reedy' assignee = 'none' closed = False closed_date = None closer = None components = ['Library (Lib)'] creation = creator = 'Woodz' dependencies = [] files = [] hgrepos = [] issue_num = 43273 keywords = [] message_count = 2.0 messages = ['387397', '387760'] nosy_count = 2.0 nosy_names = ['terry.reedy', 'Woodz'] pr_nums = [] priority = 'normal' resolution = None stage = None status = 'open' superseder = None type = None url = 'https://bugs.python.org/issue43273' versions = ['Python 3.8'] ```

9c2b5b91-db8b-4482-862f-75ed6f509b3c commented 3 years ago

I am trying to use wraps to delegate a call to a decorated patch mock to another method. By examining the source code, I was able to achieve this using the (apparently undocumented) Mock._mock_wraps attribute instead of the wraps attribute which would be expected given the constructor parameter names. I find this behaviour very confusing and inconsistent. Can we either expose Mock.wraps attribute or document _mock_wraps accordingly?

Example:

class MockRepro(unittest.TestCase)

@patch('foo') def test_side_effect(self, mock_foo): # Set side effect in constructor as per https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock Mock(side_effect = [1, 2]) # Or can set on decorated patch foo.side_effect = [1, 2]

@patch('foo') def test_wraps(self, mock_foo): def wrapped_method(): return 3

Set wraps in constructor as per https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock

Mock(wraps=wrapped_method)

Or can set on decorated patch

foo.wraps = wrapped_method # This silently fails foo._mock_wraps = wrapped_method # Where does _mock_wraps come from?

terryjreedy commented 3 years ago

Private attributes are not documented because they are private and subject to change. Their use is at one's own risk. I don't know mock well enough to understand 'inconsistent' or comment on the change proposal.

infohash commented 4 months ago

Currently there is no way to set wraps from outside of init method. When you do foo.wraps you are just creating a new mock attribute on foo. foo._mock_wraps is a private attribute which holds the value passed to wraps in the init method.