Skip to content
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

bpo-32933: Implement dunder iter method on mock_open #5974

Merged
merged 13 commits into from Sep 12, 2018
7 changes: 7 additions & 0 deletions Lib/unittest/mock.py
Expand Up @@ -2364,6 +2364,12 @@ def _readline_side_effect():
while True:
yield type(read_data)()

def _iter_side_effect():
if handle.readline.return_value is not None:
while True:
yield handle.readline.return_value
for line in _state[0]:
yield line
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you refactor def _readline_side_effect(): to use this new method for clarity:

     def _readline_side_effect():
         yield from _iter_side_effect()
         while True:
              yield type(read_data)()


global file_spec
if file_spec is None:
Expand All @@ -2387,6 +2393,7 @@ def _readline_side_effect():
_state[1] = _readline_side_effect()
handle.readline.side_effect = _state[1]
handle.readlines.side_effect = _readlines_side_effect
handle.__iter__.side_effect = _iter_side_effect

def reset_data(*args, **kwargs):
_state[0] = _iterate_read_data(read_data)
Expand Down
8 changes: 8 additions & 0 deletions Lib/unittest/test/testmock/testmock.py
Expand Up @@ -1450,6 +1450,14 @@ def test_mock_open_reuse_issue_21750(self):
f2_data = f2.read()
self.assertEqual(f1_data, f2_data)

def test_mock_open_dunder_iter_issue_32933(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to add the issue number to the test name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was following the style of the other test methods in the same file - which is better ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, the version without the issue number is better.

mocked_open = mock.mock_open(read_data='Remarkable Bird\nThe Norwegian Blue\nBeautiful Plumage')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is too long: trim your code to fit in 79 characters.

f1 = mocked_open('a-name')
lines = [line for line in f1]
self.assertEqual(lines[0], 'Remarkable Bird\n')
self.assertEqual(lines[1], 'The Norwegian Blue\n')
self.assertEqual(lines[2], 'Beautiful Plumage')

def test_mock_open_write(self):
# Test exception in file writing write()
mock_namedtemp = mock.mock_open(mock.MagicMock(name='JLV'))
Expand Down
18 changes: 18 additions & 0 deletions Lib/unittest/test/testmock/testwith.py
Expand Up @@ -205,6 +205,24 @@ def test_readline_data(self):
result = h.readline()
self.assertEqual(result, 'foo')

def test_dunder_iter_data(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit: I'd prefer one empty line as you already did, but we should be consistent and follow the existing style in the file.

# Check that dunder_iter will return all the lines from the fake file
# Added to test Issue 32933
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to mention the issue number here too.

mock = mock_open(read_data='foo\nbar\nbaz\n')
with patch('%s.open' % __name__, mock, create=True):
h = open('bar')
lines = [l for l in h]
self.assertEqual(lines[0], 'foo\n')
self.assertEqual(lines[1], 'bar\n')
self.assertEqual(lines[2], 'baz\n')

# Check that we properly emulate a file that doesn't end in a newline
mock = mock_open(read_data='foo')
with patch('%s.open' % __name__, mock, create=True):
h = open('bar')
result = h.readline()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add another h.readline() call and check that it returns an empty string?

self.assertEqual(result, 'foo')


def test_readlines_data(self):
# Test that emulating a file that ends in a newline character works
Expand Down