Skip to content

Commit

Permalink
Open binary no encoding
Browse files Browse the repository at this point in the history
                                                                                                                            On open() binary mode should not allow an encoding argument.
                                                                                                                            If encoding is passed with binary mode, raise:
                                                                                                                            ValueError(binary mode doesn\'t take an encoding argument)

                                                                                                                            Closes pytest-dev#664.
  • Loading branch information
yaythomas authored and mrbean-bremen committed Feb 3, 2022
1 parent 4dc8615 commit 80daca8
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 1 deletion.
4 changes: 3 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ The released versions correspond to PyPi releases.
* correctly handle file system space for files opened in write mode
(see [#660](../../issues/660))
* correctly handle reading/writing pipes via file
(see [#661](../../issues/661))
(see [#661](../../issues/661))
* disallow `encoding` argument on binary `open()`
(see [#664](../../issues/664))

## [Version 4.5.4](https://pypi.python.org/pypi/pyfakefs/4.5.4) (2022-01-12)
Minor bugfix release.
Expand Down
4 changes: 4 additions & 0 deletions pyfakefs/fake_filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -5571,6 +5571,10 @@ def call(self, file_: Union[AnyStr, int],
ValueError: for an invalid mode or mode combination
"""
binary = 'b' in mode

if binary and encoding:
raise ValueError("binary mode doesn't take an encoding argument")

newline, open_modes = self._handle_file_mode(mode, newline, open_modes)

file_object, file_path, filedes, real_path = self._handle_file_arg(
Expand Down
56 changes: 56 additions & 0 deletions pyfakefs/tests/fake_filesystem_vs_real_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,50 @@ def assertFileHandleBehaviorsMatch(self, path, mode, data):
self.fail('Behaviors do not match for %s:\n %s' %
(path, '\n '.join(differences)))

def assertFileHandleOpenBehaviorsMatch(self, *args, **kwargs):
"""Compare open() function invocation between real and fake.
Runs open(*args, **kwargs) on both real and fake.
Args:
*args: args to pass through to open()
**kwargs: kwargs to pass through to open().
Returns:
None.
Raises:
AssertionError if underlying open() behavior differs from fake.
"""
real_err = None
fake_err = None
try:
with open(*args, **kwargs):
pass
except Exception as e: # pylint: disable-msg=W0703
real_err = e

try:
with self.fake_open(*args, **kwargs):
pass
except Exception as e: # pylint: disable-msg=W0703
fake_err = e

# default equal in case one is None and other is not.
is_exception_equal = (real_err == fake_err)
if real_err and fake_err:
# exception __eq__ doesn't evaluate equal ever, thus manual check.
is_exception_equal = (type(real_err) is type(fake_err) and
real_err.args == fake_err.args)

if not is_exception_equal:
msg = (
"Behaviors don't match on open with args %s & kwargs %s.\n" %
(args, kwargs))
real_err_msg = 'Real open results in: %s\n' % repr(real_err)
fake_err_msg = 'Fake open results in: %s\n' % repr(fake_err)
self.fail(msg + real_err_msg + fake_err_msg)

# Helpers for checks which are not straight method calls.
@staticmethod
def _access_real(path):
Expand Down Expand Up @@ -635,6 +679,18 @@ def test_builtin_open_modes(self):
self.assertFileHandleBehaviorsMatch('write', 'wb', 'other contents')
self.assertFileHandleBehaviorsMatch('append', 'ab', 'other contents')

# binary cannot have encoding
self.assertFileHandleOpenBehaviorsMatch('read', 'rb', encoding='enc')
self.assertFileHandleOpenBehaviorsMatch(
'write', mode='wb', encoding='enc')
self.assertFileHandleOpenBehaviorsMatch('append', 'ab', encoding='enc')

# text can have encoding
self.assertFileHandleOpenBehaviorsMatch('read', 'r', encoding='utf-8')
self.assertFileHandleOpenBehaviorsMatch('write', 'w', encoding='utf-8')
self.assertFileHandleOpenBehaviorsMatch(
'append', 'a', encoding='utf-8')


def main(_):
unittest.main()
Expand Down

0 comments on commit 80daca8

Please sign in to comment.