Skip to content

Commit 878bc8b

Browse files
authored
bpo-43651: Fix EncodingWarning in fileinput and its test (GH-25648)
1 parent caae717 commit 878bc8b

File tree

2 files changed

+39
-35
lines changed

2 files changed

+39
-35
lines changed

Lib/fileinput.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,8 @@ def __init__(self, files=None, inplace=False, backup="", *,
210210

211211
# We can not use io.text_encoding() here because old openhook doesn't
212212
# take encoding parameter.
213-
if "b" not in mode and encoding is None and sys.flags.warn_default_encoding:
213+
if (sys.flags.warn_default_encoding and
214+
"b" not in mode and encoding is None and openhook is None):
214215
import warnings
215216
warnings.warn("'encoding' argument not specified.",
216217
EncodingWarning, 2)
@@ -330,6 +331,13 @@ def _readline(self):
330331
self._file = None
331332
self._isstdin = False
332333
self._backupfilename = 0
334+
335+
# EncodingWarning is emitted in __init__() already
336+
if "b" not in self._mode:
337+
encoding = self._encoding or "locale"
338+
else:
339+
encoding = None
340+
333341
if self._filename == '-':
334342
self._filename = '<stdin>'
335343
if 'b' in self._mode:
@@ -347,18 +355,18 @@ def _readline(self):
347355
pass
348356
# The next few lines may raise OSError
349357
os.rename(self._filename, self._backupfilename)
350-
self._file = open(self._backupfilename, self._mode)
358+
self._file = open(self._backupfilename, self._mode, encoding=encoding)
351359
try:
352360
perm = os.fstat(self._file.fileno()).st_mode
353361
except OSError:
354-
self._output = open(self._filename, self._write_mode)
362+
self._output = open(self._filename, self._write_mode, encoding=encoding)
355363
else:
356364
mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC
357365
if hasattr(os, 'O_BINARY'):
358366
mode |= os.O_BINARY
359367

360368
fd = os.open(self._filename, mode, perm)
361-
self._output = os.fdopen(fd, self._write_mode)
369+
self._output = os.fdopen(fd, self._write_mode, encoding=encoding)
362370
try:
363371
os.chmod(self._filename, perm)
364372
except OSError:
@@ -376,11 +384,6 @@ def _readline(self):
376384
self._file = self._openhook(
377385
self._filename, self._mode, encoding=self._encoding, errors=self._errors)
378386
else:
379-
# EncodingWarning is emitted in __init__() already
380-
if "b" not in self._mode:
381-
encoding = self._encoding or "locale"
382-
else:
383-
encoding = None
384387
self._file = open(self._filename, self._mode, encoding=encoding, errors=self._errors)
385388
self._readline = self._file.readline # hide FileInput._readline
386389
return self._readline()

Lib/test/test_fileinput.py

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class BaseTests:
4444
def writeTmp(self, content, *, mode='w'): # opening in text mode is the default
4545
fd, name = tempfile.mkstemp()
4646
self.addCleanup(os_helper.unlink, name)
47-
with open(fd, mode) as f:
47+
encoding = None if "b" in mode else "utf-8"
48+
with open(fd, mode, encoding=encoding) as f:
4849
f.write(content)
4950
return name
5051

@@ -96,7 +97,7 @@ def test_buffer_sizes(self):
9697

9798
if verbose:
9899
print('1. Simple iteration')
99-
fi = FileInput(files=(t1, t2, t3, t4))
100+
fi = FileInput(files=(t1, t2, t3, t4), encoding="utf-8")
100101
lines = list(fi)
101102
fi.close()
102103
self.assertEqual(len(lines), 31)
@@ -107,7 +108,7 @@ def test_buffer_sizes(self):
107108

108109
if verbose:
109110
print('2. Status variables')
110-
fi = FileInput(files=(t1, t2, t3, t4))
111+
fi = FileInput(files=(t1, t2, t3, t4), encoding="utf-8")
111112
s = "x"
112113
while s and s != 'Line 6 of file 2\n':
113114
s = fi.readline()
@@ -126,7 +127,7 @@ def test_buffer_sizes(self):
126127

127128
if verbose:
128129
print('4. Stdin')
129-
fi = FileInput(files=(t1, t2, t3, t4, '-'))
130+
fi = FileInput(files=(t1, t2, t3, t4, '-'), encoding="utf-8")
130131
savestdin = sys.stdin
131132
try:
132133
sys.stdin = StringIO("Line 1 of stdin\nLine 2 of stdin\n")
@@ -140,7 +141,7 @@ def test_buffer_sizes(self):
140141

141142
if verbose:
142143
print('5. Boundary conditions')
143-
fi = FileInput(files=(t1, t2, t3, t4))
144+
fi = FileInput(files=(t1, t2, t3, t4), encoding="utf-8")
144145
self.assertEqual(fi.lineno(), 0)
145146
self.assertEqual(fi.filename(), None)
146147
fi.nextfile()
@@ -151,15 +152,15 @@ def test_buffer_sizes(self):
151152
print('6. Inplace')
152153
savestdout = sys.stdout
153154
try:
154-
fi = FileInput(files=(t1, t2, t3, t4), inplace=1)
155+
fi = FileInput(files=(t1, t2, t3, t4), inplace=1, encoding="utf-8")
155156
for line in fi:
156157
line = line[:-1].upper()
157158
print(line)
158159
fi.close()
159160
finally:
160161
sys.stdout = savestdout
161162

162-
fi = FileInput(files=(t1, t2, t3, t4))
163+
fi = FileInput(files=(t1, t2, t3, t4), encoding="utf-8")
163164
for line in fi:
164165
self.assertEqual(line[-1], '\n')
165166
m = pat.match(line[:-1])
@@ -182,7 +183,7 @@ def test_zero_byte_files(self):
182183
t2 = self.writeTmp("")
183184
t3 = self.writeTmp("The only line there is.\n")
184185
t4 = self.writeTmp("")
185-
fi = FileInput(files=(t1, t2, t3, t4))
186+
fi = FileInput(files=(t1, t2, t3, t4), encoding="utf-8")
186187

187188
line = fi.readline()
188189
self.assertEqual(line, 'The only line there is.\n')
@@ -200,7 +201,7 @@ def test_zero_byte_files(self):
200201
def test_files_that_dont_end_with_newline(self):
201202
t1 = self.writeTmp("A\nB\nC")
202203
t2 = self.writeTmp("D\nE\nF")
203-
fi = FileInput(files=(t1, t2))
204+
fi = FileInput(files=(t1, t2), encoding="utf-8")
204205
lines = list(fi)
205206
self.assertEqual(lines, ["A\n", "B\n", "C", "D\n", "E\n", "F"])
206207
self.assertEqual(fi.filelineno(), 3)
@@ -213,14 +214,14 @@ def test_files_that_dont_end_with_newline(self):
213214
## encoding = sys.getfilesystemencoding()
214215
## if encoding is None:
215216
## encoding = 'ascii'
216-
## fi = FileInput(files=str(t1, encoding))
217+
## fi = FileInput(files=str(t1, encoding), encoding="utf-8")
217218
## lines = list(fi)
218219
## self.assertEqual(lines, ["A\n", "B"])
219220

220221
def test_fileno(self):
221222
t1 = self.writeTmp("A\nB")
222223
t2 = self.writeTmp("C\nD")
223-
fi = FileInput(files=(t1, t2))
224+
fi = FileInput(files=(t1, t2), encoding="utf-8")
224225
self.assertEqual(fi.fileno(), -1)
225226
line = next(fi)
226227
self.assertNotEqual(fi.fileno(), -1)
@@ -232,7 +233,7 @@ def test_fileno(self):
232233
def test_opening_mode(self):
233234
try:
234235
# invalid mode, should raise ValueError
235-
fi = FileInput(mode="w")
236+
fi = FileInput(mode="w", encoding="utf-8")
236237
self.fail("FileInput should reject invalid mode argument")
237238
except ValueError:
238239
pass
@@ -281,7 +282,7 @@ def __init__(self):
281282
self.invoked = False
282283
def __call__(self, *args, **kargs):
283284
self.invoked = True
284-
return open(*args)
285+
return open(*args, encoding="utf-8")
285286

286287
t = self.writeTmp("\n")
287288
custom_open_hook = CustomOpenHook()
@@ -346,7 +347,7 @@ def old_hook(filename, mode):
346347
def test_context_manager(self):
347348
t1 = self.writeTmp("A\nB\nC")
348349
t2 = self.writeTmp("D\nE\nF")
349-
with FileInput(files=(t1, t2)) as fi:
350+
with FileInput(files=(t1, t2), encoding="utf-8") as fi:
350351
lines = list(fi)
351352
self.assertEqual(lines, ["A\n", "B\n", "C", "D\n", "E\n", "F"])
352353
self.assertEqual(fi.filelineno(), 3)
@@ -356,21 +357,21 @@ def test_context_manager(self):
356357
def test_close_on_exception(self):
357358
t1 = self.writeTmp("")
358359
try:
359-
with FileInput(files=t1) as fi:
360+
with FileInput(files=t1, encoding="utf-8") as fi:
360361
raise OSError
361362
except OSError:
362363
self.assertEqual(fi._files, ())
363364

364365
def test_empty_files_list_specified_to_constructor(self):
365-
with FileInput(files=[]) as fi:
366+
with FileInput(files=[], encoding="utf-8") as fi:
366367
self.assertEqual(fi._files, ('-',))
367368

368369
@warnings_helper.ignore_warnings(category=DeprecationWarning)
369370
def test__getitem__(self):
370371
"""Tests invoking FileInput.__getitem__() with the current
371372
line number"""
372373
t = self.writeTmp("line1\nline2\n")
373-
with FileInput(files=[t]) as fi:
374+
with FileInput(files=[t], encoding="utf-8") as fi:
374375
retval1 = fi[0]
375376
self.assertEqual(retval1, "line1\n")
376377
retval2 = fi[1]
@@ -388,7 +389,7 @@ def test__getitem__invalid_key(self):
388389
"""Tests invoking FileInput.__getitem__() with an index unequal to
389390
the line number"""
390391
t = self.writeTmp("line1\nline2\n")
391-
with FileInput(files=[t]) as fi:
392+
with FileInput(files=[t], encoding="utf-8") as fi:
392393
with self.assertRaises(RuntimeError) as cm:
393394
fi[1]
394395
self.assertEqual(cm.exception.args, ("accessing lines out of order",))
@@ -398,7 +399,7 @@ def test__getitem__eof(self):
398399
"""Tests invoking FileInput.__getitem__() with the line number but at
399400
end-of-input"""
400401
t = self.writeTmp('')
401-
with FileInput(files=[t]) as fi:
402+
with FileInput(files=[t], encoding="utf-8") as fi:
402403
with self.assertRaises(IndexError) as cm:
403404
fi[0]
404405
self.assertEqual(cm.exception.args, ("end of input reached",))
@@ -413,7 +414,7 @@ def test_nextfile_oserror_deleting_backup(self):
413414
try:
414415
t = self.writeTmp("\n")
415416
self.addCleanup(safe_unlink, t + '.bak')
416-
with FileInput(files=[t], inplace=True) as fi:
417+
with FileInput(files=[t], inplace=True, encoding="utf-8") as fi:
417418
next(fi) # make sure the file is opened
418419
os.unlink = os_unlink_replacement
419420
fi.nextfile()
@@ -432,7 +433,7 @@ def test_readline_os_fstat_raises_OSError(self):
432433
os_fstat_replacement = UnconditionallyRaise(OSError)
433434
try:
434435
t = self.writeTmp("\n")
435-
with FileInput(files=[t], inplace=True) as fi:
436+
with FileInput(files=[t], inplace=True, encoding="utf-8") as fi:
436437
os.fstat = os_fstat_replacement
437438
fi.readline()
438439
finally:
@@ -450,7 +451,7 @@ def test_readline_os_chmod_raises_OSError(self):
450451
os_chmod_replacement = UnconditionallyRaise(OSError)
451452
try:
452453
t = self.writeTmp("\n")
453-
with FileInput(files=[t], inplace=True) as fi:
454+
with FileInput(files=[t], inplace=True, encoding="utf-8") as fi:
454455
os.chmod = os_chmod_replacement
455456
fi.readline()
456457
finally:
@@ -469,7 +470,7 @@ def fileno(self):
469470

470471
unconditionally_raise_ValueError = FilenoRaisesValueError()
471472
t = self.writeTmp("\n")
472-
with FileInput(files=[t]) as fi:
473+
with FileInput(files=[t], encoding="utf-8") as fi:
473474
file_backup = fi._file
474475
try:
475476
fi._file = unconditionally_raise_ValueError
@@ -517,7 +518,7 @@ def test_iteration_buffering(self):
517518

518519
def test_pathlib_file(self):
519520
t1 = Path(self.writeTmp("Pathlib file."))
520-
with FileInput(t1) as fi:
521+
with FileInput(t1, encoding="utf-8") as fi:
521522
line = fi.readline()
522523
self.assertEqual(line, 'Pathlib file.')
523524
self.assertEqual(fi.lineno(), 1)
@@ -526,11 +527,11 @@ def test_pathlib_file(self):
526527

527528
def test_pathlib_file_inplace(self):
528529
t1 = Path(self.writeTmp('Pathlib file.'))
529-
with FileInput(t1, inplace=True) as fi:
530+
with FileInput(t1, inplace=True, encoding="utf-8") as fi:
530531
line = fi.readline()
531532
self.assertEqual(line, 'Pathlib file.')
532533
print('Modified %s' % line)
533-
with open(t1) as f:
534+
with open(t1, encoding="utf-8") as f:
534535
self.assertEqual(f.read(), 'Modified Pathlib file.\n')
535536

536537

0 commit comments

Comments
 (0)