mirror of
				https://github.com/python/cpython.git
				synced 2025-11-01 06:01:29 +00:00 
			
		
		
		
	Issue #21750: mock_open.read_data can now be read from each instance, as it
could in Python 3.3.
This commit is contained in:
		
							parent
							
								
									579db160b3
								
							
						
					
					
						commit
						5329aaa74b
					
				
					 4 changed files with 57 additions and 31 deletions
				
			
		|  | @ -2265,6 +2265,7 @@ def _iterate_read_data(read_data): | |||
|     for line in data_as_list: | ||||
|         yield line | ||||
| 
 | ||||
| 
 | ||||
| def mock_open(mock=None, read_data=''): | ||||
|     """ | ||||
|     A helper function to create a mock to replace the use of `open`. It works | ||||
|  | @ -2277,24 +2278,6 @@ def mock_open(mock=None, read_data=''): | |||
|     `read_data` is a string for the `read` methoddline`, and `readlines` of the | ||||
|     file handle to return.  This is an empty string by default. | ||||
|     """ | ||||
|     def _readlines_side_effect(*args, **kwargs): | ||||
|         if handle.readlines.return_value is not None: | ||||
|             return handle.readlines.return_value | ||||
|         return list(_data) | ||||
| 
 | ||||
|     def _read_side_effect(*args, **kwargs): | ||||
|         if handle.read.return_value is not None: | ||||
|             return handle.read.return_value | ||||
|         return ''.join(_data) | ||||
| 
 | ||||
|     def _readline_side_effect(): | ||||
|         if handle.readline.return_value is not None: | ||||
|             while True: | ||||
|                 yield handle.readline.return_value | ||||
|         for line in _data: | ||||
|             yield line | ||||
| 
 | ||||
| 
 | ||||
|     global file_spec | ||||
|     if file_spec is None: | ||||
|         import _io | ||||
|  | @ -2303,21 +2286,42 @@ def _readline_side_effect(): | |||
|     if mock is None: | ||||
|         mock = MagicMock(name='open', spec=open) | ||||
| 
 | ||||
|     handle = MagicMock(spec=file_spec) | ||||
|     handle.__enter__.return_value = handle | ||||
|     def make_handle(*args, **kwargs): | ||||
|         # Arg checking is handled by __call__ | ||||
|         def _readlines_side_effect(*args, **kwargs): | ||||
|             if handle.readlines.return_value is not None: | ||||
|                 return handle.readlines.return_value | ||||
|             return list(_data) | ||||
| 
 | ||||
|     _data = _iterate_read_data(read_data) | ||||
|         def _read_side_effect(*args, **kwargs): | ||||
|             if handle.read.return_value is not None: | ||||
|                 return handle.read.return_value | ||||
|             return ''.join(_data) | ||||
| 
 | ||||
|     handle.write.return_value = None | ||||
|     handle.read.return_value = None | ||||
|     handle.readline.return_value = None | ||||
|     handle.readlines.return_value = None | ||||
|         def _readline_side_effect(): | ||||
|             if handle.readline.return_value is not None: | ||||
|                 while True: | ||||
|                     yield handle.readline.return_value | ||||
|             for line in _data: | ||||
|                 yield line | ||||
| 
 | ||||
|     handle.read.side_effect = _read_side_effect | ||||
|     handle.readline.side_effect = _readline_side_effect() | ||||
|     handle.readlines.side_effect = _readlines_side_effect | ||||
|         handle = MagicMock(spec=file_spec) | ||||
|         handle.__enter__.return_value = handle | ||||
| 
 | ||||
|     mock.return_value = handle | ||||
|         _data = _iterate_read_data(read_data) | ||||
| 
 | ||||
|         handle.write.return_value = None | ||||
|         handle.read.return_value = None | ||||
|         handle.readline.return_value = None | ||||
|         handle.readlines.return_value = None | ||||
| 
 | ||||
|         handle.read.side_effect = _read_side_effect | ||||
|         handle.readline.side_effect = _readline_side_effect() | ||||
|         handle.readlines.side_effect = _readlines_side_effect | ||||
|         _check_and_set_parent(mock, handle, None, '()') | ||||
|         return handle | ||||
| 
 | ||||
|     mock.side_effect = make_handle | ||||
|     return mock | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1326,6 +1326,11 @@ def test_magic_methods_mock_calls(self): | |||
|             self.assertEqual(m.mock_calls, [call.__int__(), call.__float__()]) | ||||
|             self.assertEqual(m.method_calls, []) | ||||
| 
 | ||||
|     def test_mock_open_reuse_issue_21750(self): | ||||
|         mocked_open = mock.mock_open(read_data='data') | ||||
|         f1 = mocked_open('a-name') | ||||
|         f2 = mocked_open('another-name') | ||||
|         self.assertEqual(f1.read(), f2.read()) | ||||
| 
 | ||||
|     def test_mock_parents(self): | ||||
|         for Klass in Mock, MagicMock: | ||||
|  |  | |||
|  | @ -141,7 +141,6 @@ def test_mock_open(self): | |||
| 
 | ||||
|     def test_mock_open_context_manager(self): | ||||
|         mock = mock_open() | ||||
|         handle = mock.return_value | ||||
|         with patch('%s.open' % __name__, mock, create=True): | ||||
|             with open('foo') as f: | ||||
|                 f.read() | ||||
|  | @ -149,8 +148,23 @@ def test_mock_open_context_manager(self): | |||
|         expected_calls = [call('foo'), call().__enter__(), call().read(), | ||||
|                           call().__exit__(None, None, None)] | ||||
|         self.assertEqual(mock.mock_calls, expected_calls) | ||||
|         self.assertIs(f, handle) | ||||
|         # mock_open.return_value is no longer static, because | ||||
|         # readline support requires that it mutate state | ||||
| 
 | ||||
|     def test_mock_open_context_manager_multiple_times(self): | ||||
|         mock = mock_open() | ||||
|         with patch('%s.open' % __name__, mock, create=True): | ||||
|             with open('foo') as f: | ||||
|                 f.read() | ||||
|             with open('bar') as f: | ||||
|                 f.read() | ||||
| 
 | ||||
|         expected_calls = [ | ||||
|             call('foo'), call().__enter__(), call().read(), | ||||
|             call().__exit__(None, None, None), | ||||
|             call('bar'), call().__enter__(), call().read(), | ||||
|             call().__exit__(None, None, None)] | ||||
|         self.assertEqual(mock.mock_calls, expected_calls) | ||||
| 
 | ||||
|     def test_explicit_mock(self): | ||||
|         mock = MagicMock() | ||||
|  |  | |||
|  | @ -66,6 +66,9 @@ Core and Builtins | |||
| Library | ||||
| ------- | ||||
| 
 | ||||
| - Issue #21750: mock_open.read_data can now be read from each instance, as it | ||||
|   could in Python 3.3. | ||||
| 
 | ||||
| - Issue #23247: Fix a crash in the StreamWriter.reset() of CJK codecs. | ||||
| 
 | ||||
| - Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Robert Collins
						Robert Collins