mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +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:
 | 
					    for line in data_as_list:
 | 
				
			||||||
        yield line
 | 
					        yield line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def mock_open(mock=None, read_data=''):
 | 
					def mock_open(mock=None, read_data=''):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    A helper function to create a mock to replace the use of `open`. It works
 | 
					    A helper function to create a mock to replace the use of `open`. It works
 | 
				
			||||||
| 
						 | 
					@ -2277,6 +2278,16 @@ def mock_open(mock=None, read_data=''):
 | 
				
			||||||
    `read_data` is a string for the `read` methoddline`, and `readlines` of the
 | 
					    `read_data` is a string for the `read` methoddline`, and `readlines` of the
 | 
				
			||||||
    file handle to return.  This is an empty string by default.
 | 
					    file handle to return.  This is an empty string by default.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					    global file_spec
 | 
				
			||||||
 | 
					    if file_spec is None:
 | 
				
			||||||
 | 
					        import _io
 | 
				
			||||||
 | 
					        file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if mock is None:
 | 
				
			||||||
 | 
					        mock = MagicMock(name='open', spec=open)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def make_handle(*args, **kwargs):
 | 
				
			||||||
 | 
					        # Arg checking is handled by __call__
 | 
				
			||||||
        def _readlines_side_effect(*args, **kwargs):
 | 
					        def _readlines_side_effect(*args, **kwargs):
 | 
				
			||||||
            if handle.readlines.return_value is not None:
 | 
					            if handle.readlines.return_value is not None:
 | 
				
			||||||
                return handle.readlines.return_value
 | 
					                return handle.readlines.return_value
 | 
				
			||||||
| 
						 | 
					@ -2294,15 +2305,6 @@ def mock_open(mock=None, read_data=''):
 | 
				
			||||||
            for line in _data:
 | 
					            for line in _data:
 | 
				
			||||||
                yield line
 | 
					                yield line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    global file_spec
 | 
					 | 
				
			||||||
    if file_spec is None:
 | 
					 | 
				
			||||||
        import _io
 | 
					 | 
				
			||||||
        file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if mock is None:
 | 
					 | 
				
			||||||
        mock = MagicMock(name='open', spec=open)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        handle = MagicMock(spec=file_spec)
 | 
					        handle = MagicMock(spec=file_spec)
 | 
				
			||||||
        handle.__enter__.return_value = handle
 | 
					        handle.__enter__.return_value = handle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2316,8 +2318,10 @@ def mock_open(mock=None, read_data=''):
 | 
				
			||||||
        handle.read.side_effect = _read_side_effect
 | 
					        handle.read.side_effect = _read_side_effect
 | 
				
			||||||
        handle.readline.side_effect = _readline_side_effect()
 | 
					        handle.readline.side_effect = _readline_side_effect()
 | 
				
			||||||
        handle.readlines.side_effect = _readlines_side_effect
 | 
					        handle.readlines.side_effect = _readlines_side_effect
 | 
				
			||||||
 | 
					        _check_and_set_parent(mock, handle, None, '()')
 | 
				
			||||||
 | 
					        return handle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mock.return_value = handle
 | 
					    mock.side_effect = make_handle
 | 
				
			||||||
    return mock
 | 
					    return mock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1326,6 +1326,11 @@ class MockTest(unittest.TestCase):
 | 
				
			||||||
            self.assertEqual(m.mock_calls, [call.__int__(), call.__float__()])
 | 
					            self.assertEqual(m.mock_calls, [call.__int__(), call.__float__()])
 | 
				
			||||||
            self.assertEqual(m.method_calls, [])
 | 
					            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):
 | 
					    def test_mock_parents(self):
 | 
				
			||||||
        for Klass in Mock, MagicMock:
 | 
					        for Klass in Mock, MagicMock:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -141,7 +141,6 @@ class TestMockOpen(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_mock_open_context_manager(self):
 | 
					    def test_mock_open_context_manager(self):
 | 
				
			||||||
        mock = mock_open()
 | 
					        mock = mock_open()
 | 
				
			||||||
        handle = mock.return_value
 | 
					 | 
				
			||||||
        with patch('%s.open' % __name__, mock, create=True):
 | 
					        with patch('%s.open' % __name__, mock, create=True):
 | 
				
			||||||
            with open('foo') as f:
 | 
					            with open('foo') as f:
 | 
				
			||||||
                f.read()
 | 
					                f.read()
 | 
				
			||||||
| 
						 | 
					@ -149,8 +148,23 @@ class TestMockOpen(unittest.TestCase):
 | 
				
			||||||
        expected_calls = [call('foo'), call().__enter__(), call().read(),
 | 
					        expected_calls = [call('foo'), call().__enter__(), call().read(),
 | 
				
			||||||
                          call().__exit__(None, None, None)]
 | 
					                          call().__exit__(None, None, None)]
 | 
				
			||||||
        self.assertEqual(mock.mock_calls, expected_calls)
 | 
					        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):
 | 
					    def test_explicit_mock(self):
 | 
				
			||||||
        mock = MagicMock()
 | 
					        mock = MagicMock()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,6 +66,9 @@ Core and Builtins
 | 
				
			||||||
Library
 | 
					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 #23247: Fix a crash in the StreamWriter.reset() of CJK codecs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely.
 | 
					- Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue