Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
4838717b
Commit
4838717b
authored
Jul 17, 2015
by
Robert Collins
Browse files
Options
Browse Files
Download
Plain Diff
Issue #21750: mock_open.read_data can now be read from each instance, as it
could in Python 3.3.
parents
2237bdc5
5329aaa7
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
61 additions
and
35 deletions
+61
-35
Lib/unittest/mock.py
Lib/unittest/mock.py
+37
-33
Lib/unittest/test/testmock/testmock.py
Lib/unittest/test/testmock/testmock.py
+5
-0
Lib/unittest/test/testmock/testwith.py
Lib/unittest/test/testmock/testwith.py
+16
-2
Misc/NEWS
Misc/NEWS
+3
-0
No files found.
Lib/unittest/mock.py
View file @
4838717b
...
...
@@ -2286,6 +2286,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
...
...
@@ -2298,24 +2299,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
...
...
@@ -2324,21 +2307,42 @@ def mock_open(mock=None, read_data=''):
if
mock
is
None
:
mock
=
MagicMock
(
name
=
'open'
,
spec
=
open
)
handle
=
MagicMock
(
spec
=
file_spec
)
handle
.
__enter__
.
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
mock
.
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
)
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
handle
=
MagicMock
(
spec
=
file_spec
)
handle
.
__enter__
.
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
...
...
Lib/unittest/test/testmock/testmock.py
View file @
4838717b
...
...
@@ -1371,6 +1371,11 @@ class MockTest(unittest.TestCase):
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:
...
...
Lib/unittest/test/testmock/testwith.py
View file @
4838717b
...
...
@@ -141,7 +141,6 @@ class TestMockOpen(unittest.TestCase):
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 @@ class TestMockOpen(unittest.TestCase):
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
()
...
...
Misc/NEWS
View file @
4838717b
...
...
@@ -73,6 +73,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 #24552: Fix use after free in an error case of the _pickle module.
- Issue #24514: tarfile now tolerates number fields consisting of only
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment