From 2bd1c31d86919d7c15dbc4162258210094f68c0b Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sat, 27 Apr 2019 21:11:24 +0300 Subject: [PATCH 1/2] bpo-1613500: Don't hardcode output file mode in fileinput.FileInput --- Lib/fileinput.py | 7 ++++--- Lib/test/test_fileinput.py | 10 ++++++++++ .../Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst | 3 +++ 3 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst diff --git a/Lib/fileinput.py b/Lib/fileinput.py index 4a71cc5ff31872..5769fa6a00b6cb 100644 --- a/Lib/fileinput.py +++ b/Lib/fileinput.py @@ -222,6 +222,7 @@ def __init__(self, files=None, inplace=False, backup="", bufsize=0, warnings.warn("'U' mode is deprecated", DeprecationWarning, 2) self._mode = mode + self._write_mode = mode.replace('r', 'w') if 'U' not in mode else 'w' if openhook: if inplace: raise ValueError("FileInput cannot use an opening hook in inplace mode") @@ -348,14 +349,14 @@ def _readline(self): try: perm = os.fstat(self._file.fileno()).st_mode except OSError: - self._output = open(self._filename, "w") + self._output = open(self._filename, self._write_mode) else: mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC - if hasattr(os, 'O_BINARY'): + if hasattr(os, 'O_BINARY') and 'b' in self._mode: mode |= os.O_BINARY fd = os.open(self._filename, mode, perm) - self._output = os.fdopen(fd, "w") + self._output = os.fdopen(fd, self._write_mode) try: os.chmod(self._filename, perm) except OSError: diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py index 3857401ca60fa6..8b7577b0205cde 100644 --- a/Lib/test/test_fileinput.py +++ b/Lib/test/test_fileinput.py @@ -329,6 +329,16 @@ def test_readline_binary_mode(self): self.assertEqual(fi.readline(), b'') self.assertEqual(fi.readline(), b'') + def test_inplace_binary_write_mode(self): + temp_file = self.writeTmp(b'Initial text.', mode='wb') + with FileInput(temp_file, mode='rb', inplace=True) as fobj: + line = fobj.readline() + self.assertEqual(line, b'Initial text.') + # print() cannot be used with files opened in binary mode. + sys.stdout.write(b'New line.') + with open(temp_file, 'rb') as f: + self.assertEqual(f.read(), b'New line.') + def test_context_manager(self): t1 = self.writeTmp("A\nB\nC") t2 = self.writeTmp("D\nE\nF") diff --git a/Misc/NEWS.d/next/Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst b/Misc/NEWS.d/next/Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst new file mode 100644 index 00000000000000..4501819ac360e6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst @@ -0,0 +1,3 @@ +:class:`fileinput.FileInput` now uses the input file mode to correctly set +the output file mode (previously it was hardcoded to ``'w'``) when +``inplace=True`` is passed to its constructor. From ddecd03a0b9ddfd0f3495597fcc4b34647ae52ea Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 28 Apr 2019 17:52:58 +0300 Subject: [PATCH 2/2] Update fileinput.py --- Lib/fileinput.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/fileinput.py b/Lib/fileinput.py index 5769fa6a00b6cb..0764aa5e4d2480 100644 --- a/Lib/fileinput.py +++ b/Lib/fileinput.py @@ -352,7 +352,7 @@ def _readline(self): self._output = open(self._filename, self._write_mode) else: mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC - if hasattr(os, 'O_BINARY') and 'b' in self._mode: + if hasattr(os, 'O_BINARY'): mode |= os.O_BINARY fd = os.open(self._filename, mode, perm)