blob: 819557d5e868605ff5880b9f8d5e6e3c539bca52 [file] [log] [blame]
Tim Peters3230d5c2001-07-11 22:21:17 +00001'''
2Tests for fileinput module.
3Nick Mathewson
4'''
Benjamin Petersoneb462882011-03-15 09:50:18 -05005import os
6import sys
7import re
briancurtin906f0c42011-03-15 10:29:41 -04008import fileinput
9import collections
Florent Xiclunaa011e2b2011-11-07 19:43:07 +010010import builtins
Serhiy Storchaka5f48e262018-06-05 12:08:36 +030011import tempfile
Benjamin Petersoneb462882011-03-15 09:50:18 -050012import unittest
13
briancurtinf84f3c32011-03-18 13:03:17 -050014try:
15 import bz2
16except ImportError:
17 bz2 = None
Ezio Melottic3afbb92011-05-14 10:10:53 +030018try:
19 import gzip
20except ImportError:
21 gzip = None
briancurtinf84f3c32011-03-18 13:03:17 -050022
Serhiy Storchaka946cfc32014-05-14 21:08:33 +030023from io import BytesIO, StringIO
Benjamin Petersoneb462882011-03-15 09:50:18 -050024from fileinput import FileInput, hook_encoded
Roy Williams002665a2017-05-22 22:24:17 -070025from pathlib import Path
Benjamin Petersoneb462882011-03-15 09:50:18 -050026
Serhiy Storchaka597d15a2016-04-24 13:45:58 +030027from test.support import verbose, TESTFN, check_warnings
Benjamin Petersoneb462882011-03-15 09:50:18 -050028from test.support import unlink as safe_unlink
Martin Panter7978e102016-01-16 06:26:54 +000029from test import support
Serhiy Storchaka946cfc32014-05-14 21:08:33 +030030from unittest import mock
Benjamin Petersoneb462882011-03-15 09:50:18 -050031
Tim Peters3230d5c2001-07-11 22:21:17 +000032
33# The fileinput module has 2 interfaces: the FileInput class which does
34# all the work, and a few functions (input, etc.) that use a global _state
briancurtin906f0c42011-03-15 10:29:41 -040035# variable.
Tim Peters3230d5c2001-07-11 22:21:17 +000036
Serhiy Storchaka5f48e262018-06-05 12:08:36 +030037class BaseTests:
38 # Write a content (str or bytes) to temp file, and return the
39 # temp file's name.
40 def writeTmp(self, content, *, mode='w'): # opening in text mode is the default
41 fd, name = tempfile.mkstemp()
42 self.addCleanup(support.unlink, name)
43 with open(fd, mode) as f:
44 f.write(content)
45 return name
Tim Peters3230d5c2001-07-11 22:21:17 +000046
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +020047class LineReader:
48
49 def __init__(self):
50 self._linesread = []
51
52 @property
53 def linesread(self):
54 try:
55 return self._linesread[:]
56 finally:
57 self._linesread = []
58
59 def openhook(self, filename, mode):
60 self.it = iter(filename.splitlines(True))
61 return self
62
63 def readline(self, size=None):
64 line = next(self.it, '')
65 self._linesread.append(line)
66 return line
67
68 def readlines(self, hint=-1):
69 lines = []
70 size = 0
71 while True:
72 line = self.readline()
73 if not line:
74 return lines
75 lines.append(line)
76 size += len(line)
77 if size >= hint:
78 return lines
79
80 def close(self):
81 pass
82
Serhiy Storchaka5f48e262018-06-05 12:08:36 +030083class BufferSizesTests(BaseTests, unittest.TestCase):
Guido van Rossumd8faa362007-04-27 19:54:29 +000084 def test_buffer_sizes(self):
Tim Peters3230d5c2001-07-11 22:21:17 +000085
Matthias Bussonnier1a3faf92019-05-20 13:44:11 -070086 t1 = self.writeTmp(''.join("Line %s of file 1\n" % (i+1) for i in range(15)))
87 t2 = self.writeTmp(''.join("Line %s of file 2\n" % (i+1) for i in range(10)))
88 t3 = self.writeTmp(''.join("Line %s of file 3\n" % (i+1) for i in range(5)))
89 t4 = self.writeTmp(''.join("Line %s of file 4\n" % (i+1) for i in range(1)))
90
Guido van Rossumd8faa362007-04-27 19:54:29 +000091 pat = re.compile(r'LINE (\d+) OF FILE (\d+)')
Tim Peters3230d5c2001-07-11 22:21:17 +000092
Guido van Rossumd8faa362007-04-27 19:54:29 +000093 if verbose:
Matthias Bussonnier1a3faf92019-05-20 13:44:11 -070094 print('1. Simple iteration')
95 fi = FileInput(files=(t1, t2, t3, t4))
Tim Peters3230d5c2001-07-11 22:21:17 +000096 lines = list(fi)
Tim Peters3230d5c2001-07-11 22:21:17 +000097 fi.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +000098 self.assertEqual(len(lines), 31)
99 self.assertEqual(lines[4], 'Line 5 of file 1\n')
100 self.assertEqual(lines[30], 'Line 1 of file 4\n')
101 self.assertEqual(fi.lineno(), 31)
102 self.assertEqual(fi.filename(), t4)
Tim Peters3230d5c2001-07-11 22:21:17 +0000103
Guido van Rossumd8faa362007-04-27 19:54:29 +0000104 if verbose:
Matthias Bussonnier1a3faf92019-05-20 13:44:11 -0700105 print('2. Status variables')
106 fi = FileInput(files=(t1, t2, t3, t4))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000107 s = "x"
108 while s and s != 'Line 6 of file 2\n':
109 s = fi.readline()
110 self.assertEqual(fi.filename(), t2)
111 self.assertEqual(fi.lineno(), 21)
112 self.assertEqual(fi.filelineno(), 6)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000113 self.assertFalse(fi.isfirstline())
114 self.assertFalse(fi.isstdin())
Tim Peters3230d5c2001-07-11 22:21:17 +0000115
Guido van Rossumd8faa362007-04-27 19:54:29 +0000116 if verbose:
Matthias Bussonnier1a3faf92019-05-20 13:44:11 -0700117 print('3. Nextfile')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000118 fi.nextfile()
119 self.assertEqual(fi.readline(), 'Line 1 of file 3\n')
120 self.assertEqual(fi.lineno(), 22)
121 fi.close()
Tim Peters3230d5c2001-07-11 22:21:17 +0000122
Guido van Rossumd8faa362007-04-27 19:54:29 +0000123 if verbose:
Matthias Bussonnier1a3faf92019-05-20 13:44:11 -0700124 print('4. Stdin')
125 fi = FileInput(files=(t1, t2, t3, t4, '-'))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000126 savestdin = sys.stdin
127 try:
128 sys.stdin = StringIO("Line 1 of stdin\nLine 2 of stdin\n")
129 lines = list(fi)
130 self.assertEqual(len(lines), 33)
131 self.assertEqual(lines[32], 'Line 2 of stdin\n')
132 self.assertEqual(fi.filename(), '<stdin>')
133 fi.nextfile()
134 finally:
135 sys.stdin = savestdin
Tim Peters3230d5c2001-07-11 22:21:17 +0000136
Guido van Rossumd8faa362007-04-27 19:54:29 +0000137 if verbose:
Matthias Bussonnier1a3faf92019-05-20 13:44:11 -0700138 print('5. Boundary conditions')
139 fi = FileInput(files=(t1, t2, t3, t4))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000140 self.assertEqual(fi.lineno(), 0)
141 self.assertEqual(fi.filename(), None)
142 fi.nextfile()
143 self.assertEqual(fi.lineno(), 0)
144 self.assertEqual(fi.filename(), None)
Tim Peters3230d5c2001-07-11 22:21:17 +0000145
Guido van Rossumd8faa362007-04-27 19:54:29 +0000146 if verbose:
Matthias Bussonnier1a3faf92019-05-20 13:44:11 -0700147 print('6. Inplace')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000148 savestdout = sys.stdout
149 try:
Matthias Bussonnier1a3faf92019-05-20 13:44:11 -0700150 fi = FileInput(files=(t1, t2, t3, t4), inplace=1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000151 for line in fi:
152 line = line[:-1].upper()
153 print(line)
154 fi.close()
155 finally:
156 sys.stdout = savestdout
Tim Peters3230d5c2001-07-11 22:21:17 +0000157
Matthias Bussonnier1a3faf92019-05-20 13:44:11 -0700158 fi = FileInput(files=(t1, t2, t3, t4))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000159 for line in fi:
160 self.assertEqual(line[-1], '\n')
161 m = pat.match(line[:-1])
162 self.assertNotEqual(m, None)
163 self.assertEqual(int(m.group(1)), fi.filelineno())
164 fi.close()
Georg Brandle4662172006-02-19 09:51:27 +0000165
briancurtin906f0c42011-03-15 10:29:41 -0400166class UnconditionallyRaise:
167 def __init__(self, exception_type):
168 self.exception_type = exception_type
169 self.invoked = False
170 def __call__(self, *args, **kwargs):
171 self.invoked = True
172 raise self.exception_type()
173
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300174class FileInputTests(BaseTests, unittest.TestCase):
briancurtin906f0c42011-03-15 10:29:41 -0400175
Guido van Rossumd8faa362007-04-27 19:54:29 +0000176 def test_zero_byte_files(self):
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300177 t1 = self.writeTmp("")
178 t2 = self.writeTmp("")
179 t3 = self.writeTmp("The only line there is.\n")
180 t4 = self.writeTmp("")
181 fi = FileInput(files=(t1, t2, t3, t4))
Georg Brandl67e9fb92006-02-19 13:56:17 +0000182
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300183 line = fi.readline()
184 self.assertEqual(line, 'The only line there is.\n')
185 self.assertEqual(fi.lineno(), 1)
186 self.assertEqual(fi.filelineno(), 1)
187 self.assertEqual(fi.filename(), t3)
Georg Brandlc029f872006-02-19 14:12:34 +0000188
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300189 line = fi.readline()
190 self.assertFalse(line)
191 self.assertEqual(fi.lineno(), 1)
192 self.assertEqual(fi.filelineno(), 0)
193 self.assertEqual(fi.filename(), t4)
194 fi.close()
Georg Brandlc98eeed2006-02-19 14:57:47 +0000195
Guido van Rossumd8faa362007-04-27 19:54:29 +0000196 def test_files_that_dont_end_with_newline(self):
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300197 t1 = self.writeTmp("A\nB\nC")
198 t2 = self.writeTmp("D\nE\nF")
199 fi = FileInput(files=(t1, t2))
200 lines = list(fi)
201 self.assertEqual(lines, ["A\n", "B\n", "C", "D\n", "E\n", "F"])
202 self.assertEqual(fi.filelineno(), 3)
203 self.assertEqual(fi.lineno(), 6)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000204
Guido van Rossumc43e79f2007-06-18 18:26:36 +0000205## def test_unicode_filenames(self):
206## # XXX A unicode string is always returned by writeTmp.
207## # So is this needed?
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300208## t1 = self.writeTmp("A\nB")
209## encoding = sys.getfilesystemencoding()
210## if encoding is None:
211## encoding = 'ascii'
212## fi = FileInput(files=str(t1, encoding))
213## lines = list(fi)
214## self.assertEqual(lines, ["A\n", "B"])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000215
216 def test_fileno(self):
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300217 t1 = self.writeTmp("A\nB")
218 t2 = self.writeTmp("C\nD")
219 fi = FileInput(files=(t1, t2))
220 self.assertEqual(fi.fileno(), -1)
221 line = next(fi)
222 self.assertNotEqual(fi.fileno(), -1)
223 fi.nextfile()
224 self.assertEqual(fi.fileno(), -1)
225 line = list(fi)
226 self.assertEqual(fi.fileno(), -1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000227
228 def test_opening_mode(self):
Victor Stinnere471e722019-10-28 15:40:08 +0100229 # invalid modes
230 for mode in ('w', 'rU', 'U'):
231 with self.subTest(mode=mode):
232 with self.assertRaises(ValueError):
233 FileInput(mode=mode)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000234
Serhiy Storchaka946cfc32014-05-14 21:08:33 +0300235 def test_stdin_binary_mode(self):
236 with mock.patch('sys.stdin') as m_stdin:
237 m_stdin.buffer = BytesIO(b'spam, bacon, sausage, and spam')
238 fi = FileInput(files=['-'], mode='rb')
239 lines = list(fi)
240 self.assertEqual(lines, [b'spam, bacon, sausage, and spam'])
241
R David Murray830207e2016-01-02 15:41:41 -0500242 def test_detached_stdin_binary_mode(self):
243 orig_stdin = sys.stdin
244 try:
245 sys.stdin = BytesIO(b'spam, bacon, sausage, and spam')
246 self.assertFalse(hasattr(sys.stdin, 'buffer'))
247 fi = FileInput(files=['-'], mode='rb')
248 lines = list(fi)
249 self.assertEqual(lines, [b'spam, bacon, sausage, and spam'])
250 finally:
251 sys.stdin = orig_stdin
252
Guido van Rossume22905a2007-08-27 23:09:25 +0000253 def test_file_opening_hook(self):
254 try:
255 # cannot use openhook and inplace mode
256 fi = FileInput(inplace=1, openhook=lambda f, m: None)
257 self.fail("FileInput should raise if both inplace "
258 "and openhook arguments are given")
259 except ValueError:
260 pass
261 try:
262 fi = FileInput(openhook=1)
263 self.fail("FileInput should check openhook for being callable")
264 except ValueError:
265 pass
briancurtin906f0c42011-03-15 10:29:41 -0400266
267 class CustomOpenHook:
268 def __init__(self):
269 self.invoked = False
270 def __call__(self, *args):
271 self.invoked = True
272 return open(*args)
273
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300274 t = self.writeTmp("\n")
briancurtin906f0c42011-03-15 10:29:41 -0400275 custom_open_hook = CustomOpenHook()
276 with FileInput([t], openhook=custom_open_hook) as fi:
277 fi.readline()
278 self.assertTrue(custom_open_hook.invoked, "openhook not invoked")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000279
Serhiy Storchaka517b7472014-02-26 20:59:43 +0200280 def test_readline(self):
281 with open(TESTFN, 'wb') as f:
282 f.write(b'A\nB\r\nC\r')
283 # Fill TextIOWrapper buffer.
284 f.write(b'123456789\n' * 1000)
285 # Issue #20501: readline() shouldn't read whole file.
286 f.write(b'\x80')
287 self.addCleanup(safe_unlink, TESTFN)
288
289 with FileInput(files=TESTFN,
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200290 openhook=hook_encoded('ascii')) as fi:
Serhiy Storchaka682ea5f2014-03-03 21:17:17 +0200291 try:
292 self.assertEqual(fi.readline(), 'A\n')
293 self.assertEqual(fi.readline(), 'B\n')
294 self.assertEqual(fi.readline(), 'C\n')
295 except UnicodeDecodeError:
296 self.fail('Read to end of file')
Serhiy Storchaka517b7472014-02-26 20:59:43 +0200297 with self.assertRaises(UnicodeDecodeError):
298 # Read to the end of file.
299 list(fi)
Serhiy Storchaka314464d2015-11-01 16:43:58 +0200300 self.assertEqual(fi.readline(), '')
301 self.assertEqual(fi.readline(), '')
302
303 def test_readline_binary_mode(self):
304 with open(TESTFN, 'wb') as f:
305 f.write(b'A\nB\r\nC\rD')
306 self.addCleanup(safe_unlink, TESTFN)
307
308 with FileInput(files=TESTFN, mode='rb') as fi:
309 self.assertEqual(fi.readline(), b'A\n')
310 self.assertEqual(fi.readline(), b'B\r\n')
311 self.assertEqual(fi.readline(), b'C\rD')
312 # Read to the end of file.
313 self.assertEqual(fi.readline(), b'')
314 self.assertEqual(fi.readline(), b'')
Serhiy Storchaka517b7472014-02-26 20:59:43 +0200315
Berker Peksagbe6dbfb2019-04-29 17:55:39 +0300316 def test_inplace_binary_write_mode(self):
317 temp_file = self.writeTmp(b'Initial text.', mode='wb')
318 with FileInput(temp_file, mode='rb', inplace=True) as fobj:
319 line = fobj.readline()
320 self.assertEqual(line, b'Initial text.')
321 # print() cannot be used with files opened in binary mode.
322 sys.stdout.write(b'New line.')
323 with open(temp_file, 'rb') as f:
324 self.assertEqual(f.read(), b'New line.')
325
Georg Brandl6cb7b652010-07-31 20:08:15 +0000326 def test_context_manager(self):
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300327 t1 = self.writeTmp("A\nB\nC")
328 t2 = self.writeTmp("D\nE\nF")
329 with FileInput(files=(t1, t2)) as fi:
330 lines = list(fi)
331 self.assertEqual(lines, ["A\n", "B\n", "C", "D\n", "E\n", "F"])
332 self.assertEqual(fi.filelineno(), 3)
333 self.assertEqual(fi.lineno(), 6)
334 self.assertEqual(fi._files, ())
Georg Brandl6cb7b652010-07-31 20:08:15 +0000335
336 def test_close_on_exception(self):
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300337 t1 = self.writeTmp("")
Georg Brandl6cb7b652010-07-31 20:08:15 +0000338 try:
Georg Brandl6cb7b652010-07-31 20:08:15 +0000339 with FileInput(files=t1) as fi:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200340 raise OSError
341 except OSError:
Georg Brandl6cb7b652010-07-31 20:08:15 +0000342 self.assertEqual(fi._files, ())
Georg Brandl6cb7b652010-07-31 20:08:15 +0000343
briancurtin906f0c42011-03-15 10:29:41 -0400344 def test_empty_files_list_specified_to_constructor(self):
345 with FileInput(files=[]) as fi:
Brett Cannond47af532011-03-15 15:55:12 -0400346 self.assertEqual(fi._files, ('-',))
briancurtin906f0c42011-03-15 10:29:41 -0400347
Berker Peksag84a13fb2018-08-11 09:05:04 +0300348 @support.ignore_warnings(category=DeprecationWarning)
briancurtin906f0c42011-03-15 10:29:41 -0400349 def test__getitem__(self):
350 """Tests invoking FileInput.__getitem__() with the current
351 line number"""
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300352 t = self.writeTmp("line1\nline2\n")
briancurtin906f0c42011-03-15 10:29:41 -0400353 with FileInput(files=[t]) as fi:
354 retval1 = fi[0]
355 self.assertEqual(retval1, "line1\n")
356 retval2 = fi[1]
357 self.assertEqual(retval2, "line2\n")
358
Berker Peksag84a13fb2018-08-11 09:05:04 +0300359 def test__getitem___deprecation(self):
360 t = self.writeTmp("line1\nline2\n")
361 with self.assertWarnsRegex(DeprecationWarning,
362 r'Use iterator protocol instead'):
363 with FileInput(files=[t]) as fi:
364 self.assertEqual(fi[0], "line1\n")
365
366 @support.ignore_warnings(category=DeprecationWarning)
briancurtin906f0c42011-03-15 10:29:41 -0400367 def test__getitem__invalid_key(self):
368 """Tests invoking FileInput.__getitem__() with an index unequal to
369 the line number"""
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300370 t = self.writeTmp("line1\nline2\n")
briancurtin906f0c42011-03-15 10:29:41 -0400371 with FileInput(files=[t]) as fi:
372 with self.assertRaises(RuntimeError) as cm:
373 fi[1]
Brett Cannond47af532011-03-15 15:55:12 -0400374 self.assertEqual(cm.exception.args, ("accessing lines out of order",))
briancurtin906f0c42011-03-15 10:29:41 -0400375
Berker Peksag84a13fb2018-08-11 09:05:04 +0300376 @support.ignore_warnings(category=DeprecationWarning)
briancurtin906f0c42011-03-15 10:29:41 -0400377 def test__getitem__eof(self):
378 """Tests invoking FileInput.__getitem__() with the line number but at
379 end-of-input"""
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300380 t = self.writeTmp('')
briancurtin906f0c42011-03-15 10:29:41 -0400381 with FileInput(files=[t]) as fi:
382 with self.assertRaises(IndexError) as cm:
383 fi[0]
Brett Cannond47af532011-03-15 15:55:12 -0400384 self.assertEqual(cm.exception.args, ("end of input reached",))
briancurtin906f0c42011-03-15 10:29:41 -0400385
386 def test_nextfile_oserror_deleting_backup(self):
387 """Tests invoking FileInput.nextfile() when the attempt to delete
388 the backup file would raise OSError. This error is expected to be
389 silently ignored"""
390
391 os_unlink_orig = os.unlink
392 os_unlink_replacement = UnconditionallyRaise(OSError)
393 try:
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300394 t = self.writeTmp("\n")
395 self.addCleanup(support.unlink, t + '.bak')
briancurtin906f0c42011-03-15 10:29:41 -0400396 with FileInput(files=[t], inplace=True) as fi:
397 next(fi) # make sure the file is opened
398 os.unlink = os_unlink_replacement
399 fi.nextfile()
400 finally:
401 os.unlink = os_unlink_orig
402
403 # sanity check to make sure that our test scenario was actually hit
404 self.assertTrue(os_unlink_replacement.invoked,
405 "os.unlink() was not invoked")
406
407 def test_readline_os_fstat_raises_OSError(self):
408 """Tests invoking FileInput.readline() when os.fstat() raises OSError.
409 This exception should be silently discarded."""
410
411 os_fstat_orig = os.fstat
412 os_fstat_replacement = UnconditionallyRaise(OSError)
413 try:
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300414 t = self.writeTmp("\n")
briancurtin906f0c42011-03-15 10:29:41 -0400415 with FileInput(files=[t], inplace=True) as fi:
416 os.fstat = os_fstat_replacement
417 fi.readline()
418 finally:
419 os.fstat = os_fstat_orig
420
421 # sanity check to make sure that our test scenario was actually hit
422 self.assertTrue(os_fstat_replacement.invoked,
423 "os.fstat() was not invoked")
424
briancurtin906f0c42011-03-15 10:29:41 -0400425 def test_readline_os_chmod_raises_OSError(self):
426 """Tests invoking FileInput.readline() when os.chmod() raises OSError.
427 This exception should be silently discarded."""
428
429 os_chmod_orig = os.chmod
430 os_chmod_replacement = UnconditionallyRaise(OSError)
431 try:
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300432 t = self.writeTmp("\n")
briancurtin906f0c42011-03-15 10:29:41 -0400433 with FileInput(files=[t], inplace=True) as fi:
434 os.chmod = os_chmod_replacement
435 fi.readline()
436 finally:
437 os.chmod = os_chmod_orig
438
439 # sanity check to make sure that our test scenario was actually hit
440 self.assertTrue(os_chmod_replacement.invoked,
441 "os.fstat() was not invoked")
442
443 def test_fileno_when_ValueError_raised(self):
444 class FilenoRaisesValueError(UnconditionallyRaise):
445 def __init__(self):
446 UnconditionallyRaise.__init__(self, ValueError)
447 def fileno(self):
448 self.__call__()
449
450 unconditionally_raise_ValueError = FilenoRaisesValueError()
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300451 t = self.writeTmp("\n")
briancurtin906f0c42011-03-15 10:29:41 -0400452 with FileInput(files=[t]) as fi:
453 file_backup = fi._file
454 try:
455 fi._file = unconditionally_raise_ValueError
456 result = fi.fileno()
457 finally:
458 fi._file = file_backup # make sure the file gets cleaned up
459
460 # sanity check to make sure that our test scenario was actually hit
461 self.assertTrue(unconditionally_raise_ValueError.invoked,
462 "_file.fileno() was not invoked")
463
464 self.assertEqual(result, -1, "fileno() should return -1")
465
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200466 def test_readline_buffering(self):
467 src = LineReader()
468 with FileInput(files=['line1\nline2', 'line3\n'],
469 openhook=src.openhook) as fi:
470 self.assertEqual(src.linesread, [])
471 self.assertEqual(fi.readline(), 'line1\n')
472 self.assertEqual(src.linesread, ['line1\n'])
473 self.assertEqual(fi.readline(), 'line2')
474 self.assertEqual(src.linesread, ['line2'])
475 self.assertEqual(fi.readline(), 'line3\n')
476 self.assertEqual(src.linesread, ['', 'line3\n'])
477 self.assertEqual(fi.readline(), '')
478 self.assertEqual(src.linesread, [''])
479 self.assertEqual(fi.readline(), '')
480 self.assertEqual(src.linesread, [])
481
482 def test_iteration_buffering(self):
483 src = LineReader()
484 with FileInput(files=['line1\nline2', 'line3\n'],
485 openhook=src.openhook) as fi:
486 self.assertEqual(src.linesread, [])
487 self.assertEqual(next(fi), 'line1\n')
488 self.assertEqual(src.linesread, ['line1\n'])
489 self.assertEqual(next(fi), 'line2')
490 self.assertEqual(src.linesread, ['line2'])
491 self.assertEqual(next(fi), 'line3\n')
492 self.assertEqual(src.linesread, ['', 'line3\n'])
493 self.assertRaises(StopIteration, next, fi)
494 self.assertEqual(src.linesread, [''])
495 self.assertRaises(StopIteration, next, fi)
496 self.assertEqual(src.linesread, [])
497
Roy Williams002665a2017-05-22 22:24:17 -0700498 def test_pathlib_file(self):
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300499 t1 = Path(self.writeTmp("Pathlib file."))
500 with FileInput(t1) as fi:
501 line = fi.readline()
502 self.assertEqual(line, 'Pathlib file.')
503 self.assertEqual(fi.lineno(), 1)
504 self.assertEqual(fi.filelineno(), 1)
505 self.assertEqual(fi.filename(), os.fspath(t1))
Roy Williams002665a2017-05-22 22:24:17 -0700506
Zhiming Wang06de1ae2017-09-05 01:37:24 +0800507 def test_pathlib_file_inplace(self):
Serhiy Storchaka5f48e262018-06-05 12:08:36 +0300508 t1 = Path(self.writeTmp('Pathlib file.'))
509 with FileInput(t1, inplace=True) as fi:
510 line = fi.readline()
511 self.assertEqual(line, 'Pathlib file.')
512 print('Modified %s' % line)
513 with open(t1) as f:
514 self.assertEqual(f.read(), 'Modified Pathlib file.\n')
Zhiming Wang06de1ae2017-09-05 01:37:24 +0800515
Roy Williams002665a2017-05-22 22:24:17 -0700516
briancurtin906f0c42011-03-15 10:29:41 -0400517class MockFileInput:
518 """A class that mocks out fileinput.FileInput for use during unit tests"""
519
Matthias Bussonnier1a3faf92019-05-20 13:44:11 -0700520 def __init__(self, files=None, inplace=False, backup="", *,
briancurtin906f0c42011-03-15 10:29:41 -0400521 mode="r", openhook=None):
522 self.files = files
523 self.inplace = inplace
524 self.backup = backup
briancurtin906f0c42011-03-15 10:29:41 -0400525 self.mode = mode
526 self.openhook = openhook
527 self._file = None
528 self.invocation_counts = collections.defaultdict(lambda: 0)
529 self.return_values = {}
530
531 def close(self):
532 self.invocation_counts["close"] += 1
533
534 def nextfile(self):
535 self.invocation_counts["nextfile"] += 1
536 return self.return_values["nextfile"]
537
538 def filename(self):
539 self.invocation_counts["filename"] += 1
540 return self.return_values["filename"]
541
542 def lineno(self):
543 self.invocation_counts["lineno"] += 1
544 return self.return_values["lineno"]
545
546 def filelineno(self):
547 self.invocation_counts["filelineno"] += 1
548 return self.return_values["filelineno"]
549
550 def fileno(self):
551 self.invocation_counts["fileno"] += 1
552 return self.return_values["fileno"]
553
554 def isfirstline(self):
555 self.invocation_counts["isfirstline"] += 1
556 return self.return_values["isfirstline"]
557
558 def isstdin(self):
559 self.invocation_counts["isstdin"] += 1
560 return self.return_values["isstdin"]
561
562class BaseFileInputGlobalMethodsTest(unittest.TestCase):
563 """Base class for unit tests for the global function of
564 the fileinput module."""
565
566 def setUp(self):
567 self._orig_state = fileinput._state
568 self._orig_FileInput = fileinput.FileInput
569 fileinput.FileInput = MockFileInput
570
571 def tearDown(self):
572 fileinput.FileInput = self._orig_FileInput
573 fileinput._state = self._orig_state
574
575 def assertExactlyOneInvocation(self, mock_file_input, method_name):
576 # assert that the method with the given name was invoked once
577 actual_count = mock_file_input.invocation_counts[method_name]
578 self.assertEqual(actual_count, 1, method_name)
579 # assert that no other unexpected methods were invoked
580 actual_total_count = len(mock_file_input.invocation_counts)
581 self.assertEqual(actual_total_count, 1)
582
583class Test_fileinput_input(BaseFileInputGlobalMethodsTest):
584 """Unit tests for fileinput.input()"""
585
586 def test_state_is_not_None_and_state_file_is_not_None(self):
587 """Tests invoking fileinput.input() when fileinput._state is not None
588 and its _file attribute is also not None. Expect RuntimeError to
589 be raised with a meaningful error message and for fileinput._state
590 to *not* be modified."""
591 instance = MockFileInput()
592 instance._file = object()
593 fileinput._state = instance
594 with self.assertRaises(RuntimeError) as cm:
595 fileinput.input()
596 self.assertEqual(("input() already active",), cm.exception.args)
597 self.assertIs(instance, fileinput._state, "fileinput._state")
598
599 def test_state_is_not_None_and_state_file_is_None(self):
600 """Tests invoking fileinput.input() when fileinput._state is not None
601 but its _file attribute *is* None. Expect it to create and return
602 a new fileinput.FileInput object with all method parameters passed
603 explicitly to the __init__() method; also ensure that
604 fileinput._state is set to the returned instance."""
605 instance = MockFileInput()
606 instance._file = None
607 fileinput._state = instance
608 self.do_test_call_input()
609
610 def test_state_is_None(self):
611 """Tests invoking fileinput.input() when fileinput._state is None
612 Expect it to create and return a new fileinput.FileInput object
613 with all method parameters passed explicitly to the __init__()
614 method; also ensure that fileinput._state is set to the returned
615 instance."""
616 fileinput._state = None
617 self.do_test_call_input()
618
619 def do_test_call_input(self):
620 """Tests that fileinput.input() creates a new fileinput.FileInput
621 object, passing the given parameters unmodified to
622 fileinput.FileInput.__init__(). Note that this test depends on the
623 monkey patching of fileinput.FileInput done by setUp()."""
624 files = object()
625 inplace = object()
626 backup = object()
briancurtin906f0c42011-03-15 10:29:41 -0400627 mode = object()
628 openhook = object()
629
630 # call fileinput.input() with different values for each argument
631 result = fileinput.input(files=files, inplace=inplace, backup=backup,
briancurtin906f0c42011-03-15 10:29:41 -0400632 mode=mode, openhook=openhook)
633
634 # ensure fileinput._state was set to the returned object
635 self.assertIs(result, fileinput._state, "fileinput._state")
636
637 # ensure the parameters to fileinput.input() were passed directly
638 # to FileInput.__init__()
639 self.assertIs(files, result.files, "files")
640 self.assertIs(inplace, result.inplace, "inplace")
641 self.assertIs(backup, result.backup, "backup")
briancurtin906f0c42011-03-15 10:29:41 -0400642 self.assertIs(mode, result.mode, "mode")
643 self.assertIs(openhook, result.openhook, "openhook")
644
645class Test_fileinput_close(BaseFileInputGlobalMethodsTest):
646 """Unit tests for fileinput.close()"""
647
648 def test_state_is_None(self):
649 """Tests that fileinput.close() does nothing if fileinput._state
650 is None"""
651 fileinput._state = None
652 fileinput.close()
653 self.assertIsNone(fileinput._state)
654
655 def test_state_is_not_None(self):
656 """Tests that fileinput.close() invokes close() on fileinput._state
657 and sets _state=None"""
658 instance = MockFileInput()
659 fileinput._state = instance
660 fileinput.close()
661 self.assertExactlyOneInvocation(instance, "close")
662 self.assertIsNone(fileinput._state)
663
664class Test_fileinput_nextfile(BaseFileInputGlobalMethodsTest):
665 """Unit tests for fileinput.nextfile()"""
666
667 def test_state_is_None(self):
668 """Tests fileinput.nextfile() when fileinput._state is None.
669 Ensure that it raises RuntimeError with a meaningful error message
670 and does not modify fileinput._state"""
671 fileinput._state = None
672 with self.assertRaises(RuntimeError) as cm:
673 fileinput.nextfile()
674 self.assertEqual(("no active input()",), cm.exception.args)
675 self.assertIsNone(fileinput._state)
676
677 def test_state_is_not_None(self):
678 """Tests fileinput.nextfile() when fileinput._state is not None.
679 Ensure that it invokes fileinput._state.nextfile() exactly once,
680 returns whatever it returns, and does not modify fileinput._state
681 to point to a different object."""
682 nextfile_retval = object()
683 instance = MockFileInput()
684 instance.return_values["nextfile"] = nextfile_retval
685 fileinput._state = instance
686 retval = fileinput.nextfile()
687 self.assertExactlyOneInvocation(instance, "nextfile")
688 self.assertIs(retval, nextfile_retval)
689 self.assertIs(fileinput._state, instance)
690
691class Test_fileinput_filename(BaseFileInputGlobalMethodsTest):
692 """Unit tests for fileinput.filename()"""
693
694 def test_state_is_None(self):
695 """Tests fileinput.filename() when fileinput._state is None.
696 Ensure that it raises RuntimeError with a meaningful error message
697 and does not modify fileinput._state"""
698 fileinput._state = None
699 with self.assertRaises(RuntimeError) as cm:
700 fileinput.filename()
701 self.assertEqual(("no active input()",), cm.exception.args)
702 self.assertIsNone(fileinput._state)
703
704 def test_state_is_not_None(self):
705 """Tests fileinput.filename() when fileinput._state is not None.
706 Ensure that it invokes fileinput._state.filename() exactly once,
707 returns whatever it returns, and does not modify fileinput._state
708 to point to a different object."""
709 filename_retval = object()
710 instance = MockFileInput()
711 instance.return_values["filename"] = filename_retval
712 fileinput._state = instance
713 retval = fileinput.filename()
714 self.assertExactlyOneInvocation(instance, "filename")
715 self.assertIs(retval, filename_retval)
716 self.assertIs(fileinput._state, instance)
717
718class Test_fileinput_lineno(BaseFileInputGlobalMethodsTest):
719 """Unit tests for fileinput.lineno()"""
720
721 def test_state_is_None(self):
722 """Tests fileinput.lineno() when fileinput._state is None.
723 Ensure that it raises RuntimeError with a meaningful error message
724 and does not modify fileinput._state"""
725 fileinput._state = None
726 with self.assertRaises(RuntimeError) as cm:
727 fileinput.lineno()
728 self.assertEqual(("no active input()",), cm.exception.args)
729 self.assertIsNone(fileinput._state)
730
731 def test_state_is_not_None(self):
732 """Tests fileinput.lineno() when fileinput._state is not None.
733 Ensure that it invokes fileinput._state.lineno() exactly once,
734 returns whatever it returns, and does not modify fileinput._state
735 to point to a different object."""
736 lineno_retval = object()
737 instance = MockFileInput()
738 instance.return_values["lineno"] = lineno_retval
739 fileinput._state = instance
740 retval = fileinput.lineno()
741 self.assertExactlyOneInvocation(instance, "lineno")
742 self.assertIs(retval, lineno_retval)
743 self.assertIs(fileinput._state, instance)
744
745class Test_fileinput_filelineno(BaseFileInputGlobalMethodsTest):
746 """Unit tests for fileinput.filelineno()"""
747
748 def test_state_is_None(self):
749 """Tests fileinput.filelineno() when fileinput._state is None.
750 Ensure that it raises RuntimeError with a meaningful error message
751 and does not modify fileinput._state"""
752 fileinput._state = None
753 with self.assertRaises(RuntimeError) as cm:
754 fileinput.filelineno()
755 self.assertEqual(("no active input()",), cm.exception.args)
756 self.assertIsNone(fileinput._state)
757
758 def test_state_is_not_None(self):
759 """Tests fileinput.filelineno() when fileinput._state is not None.
760 Ensure that it invokes fileinput._state.filelineno() exactly once,
761 returns whatever it returns, and does not modify fileinput._state
762 to point to a different object."""
763 filelineno_retval = object()
764 instance = MockFileInput()
765 instance.return_values["filelineno"] = filelineno_retval
766 fileinput._state = instance
767 retval = fileinput.filelineno()
768 self.assertExactlyOneInvocation(instance, "filelineno")
769 self.assertIs(retval, filelineno_retval)
770 self.assertIs(fileinput._state, instance)
771
772class Test_fileinput_fileno(BaseFileInputGlobalMethodsTest):
773 """Unit tests for fileinput.fileno()"""
774
775 def test_state_is_None(self):
776 """Tests fileinput.fileno() when fileinput._state is None.
777 Ensure that it raises RuntimeError with a meaningful error message
778 and does not modify fileinput._state"""
779 fileinput._state = None
780 with self.assertRaises(RuntimeError) as cm:
781 fileinput.fileno()
782 self.assertEqual(("no active input()",), cm.exception.args)
783 self.assertIsNone(fileinput._state)
784
785 def test_state_is_not_None(self):
786 """Tests fileinput.fileno() when fileinput._state is not None.
787 Ensure that it invokes fileinput._state.fileno() exactly once,
788 returns whatever it returns, and does not modify fileinput._state
789 to point to a different object."""
790 fileno_retval = object()
791 instance = MockFileInput()
792 instance.return_values["fileno"] = fileno_retval
793 instance.fileno_retval = fileno_retval
794 fileinput._state = instance
795 retval = fileinput.fileno()
796 self.assertExactlyOneInvocation(instance, "fileno")
797 self.assertIs(retval, fileno_retval)
798 self.assertIs(fileinput._state, instance)
799
800class Test_fileinput_isfirstline(BaseFileInputGlobalMethodsTest):
801 """Unit tests for fileinput.isfirstline()"""
802
803 def test_state_is_None(self):
804 """Tests fileinput.isfirstline() when fileinput._state is None.
805 Ensure that it raises RuntimeError with a meaningful error message
806 and does not modify fileinput._state"""
807 fileinput._state = None
808 with self.assertRaises(RuntimeError) as cm:
809 fileinput.isfirstline()
810 self.assertEqual(("no active input()",), cm.exception.args)
811 self.assertIsNone(fileinput._state)
812
813 def test_state_is_not_None(self):
814 """Tests fileinput.isfirstline() when fileinput._state is not None.
815 Ensure that it invokes fileinput._state.isfirstline() exactly once,
816 returns whatever it returns, and does not modify fileinput._state
817 to point to a different object."""
818 isfirstline_retval = object()
819 instance = MockFileInput()
820 instance.return_values["isfirstline"] = isfirstline_retval
821 fileinput._state = instance
822 retval = fileinput.isfirstline()
823 self.assertExactlyOneInvocation(instance, "isfirstline")
824 self.assertIs(retval, isfirstline_retval)
825 self.assertIs(fileinput._state, instance)
826
827class Test_fileinput_isstdin(BaseFileInputGlobalMethodsTest):
828 """Unit tests for fileinput.isstdin()"""
829
830 def test_state_is_None(self):
831 """Tests fileinput.isstdin() when fileinput._state is None.
832 Ensure that it raises RuntimeError with a meaningful error message
833 and does not modify fileinput._state"""
834 fileinput._state = None
835 with self.assertRaises(RuntimeError) as cm:
836 fileinput.isstdin()
837 self.assertEqual(("no active input()",), cm.exception.args)
838 self.assertIsNone(fileinput._state)
839
840 def test_state_is_not_None(self):
841 """Tests fileinput.isstdin() when fileinput._state is not None.
842 Ensure that it invokes fileinput._state.isstdin() exactly once,
843 returns whatever it returns, and does not modify fileinput._state
844 to point to a different object."""
845 isstdin_retval = object()
846 instance = MockFileInput()
847 instance.return_values["isstdin"] = isstdin_retval
848 fileinput._state = instance
849 retval = fileinput.isstdin()
850 self.assertExactlyOneInvocation(instance, "isstdin")
851 self.assertIs(retval, isstdin_retval)
852 self.assertIs(fileinput._state, instance)
853
854class InvocationRecorder:
855 def __init__(self):
856 self.invocation_count = 0
857 def __call__(self, *args, **kwargs):
858 self.invocation_count += 1
859 self.last_invocation = (args, kwargs)
860
861class Test_hook_compressed(unittest.TestCase):
862 """Unit tests for fileinput.hook_compressed()"""
863
864 def setUp(self):
865 self.fake_open = InvocationRecorder()
866
867 def test_empty_string(self):
868 self.do_test_use_builtin_open("", 1)
869
870 def test_no_ext(self):
871 self.do_test_use_builtin_open("abcd", 2)
872
Ezio Melottic3afbb92011-05-14 10:10:53 +0300873 @unittest.skipUnless(gzip, "Requires gzip and zlib")
briancurtin5eb35912011-03-15 10:59:36 -0400874 def test_gz_ext_fake(self):
briancurtin906f0c42011-03-15 10:29:41 -0400875 original_open = gzip.open
876 gzip.open = self.fake_open
877 try:
878 result = fileinput.hook_compressed("test.gz", 3)
879 finally:
880 gzip.open = original_open
881
882 self.assertEqual(self.fake_open.invocation_count, 1)
883 self.assertEqual(self.fake_open.last_invocation, (("test.gz", 3), {}))
884
briancurtinf84f3c32011-03-18 13:03:17 -0500885 @unittest.skipUnless(bz2, "Requires bz2")
briancurtin5eb35912011-03-15 10:59:36 -0400886 def test_bz2_ext_fake(self):
briancurtin906f0c42011-03-15 10:29:41 -0400887 original_open = bz2.BZ2File
888 bz2.BZ2File = self.fake_open
889 try:
890 result = fileinput.hook_compressed("test.bz2", 4)
891 finally:
892 bz2.BZ2File = original_open
893
894 self.assertEqual(self.fake_open.invocation_count, 1)
895 self.assertEqual(self.fake_open.last_invocation, (("test.bz2", 4), {}))
896
897 def test_blah_ext(self):
898 self.do_test_use_builtin_open("abcd.blah", 5)
899
briancurtin5eb35912011-03-15 10:59:36 -0400900 def test_gz_ext_builtin(self):
briancurtin906f0c42011-03-15 10:29:41 -0400901 self.do_test_use_builtin_open("abcd.Gz", 6)
902
briancurtin5eb35912011-03-15 10:59:36 -0400903 def test_bz2_ext_builtin(self):
briancurtin906f0c42011-03-15 10:29:41 -0400904 self.do_test_use_builtin_open("abcd.Bz2", 7)
905
906 def do_test_use_builtin_open(self, filename, mode):
907 original_open = self.replace_builtin_open(self.fake_open)
908 try:
909 result = fileinput.hook_compressed(filename, mode)
910 finally:
911 self.replace_builtin_open(original_open)
912
913 self.assertEqual(self.fake_open.invocation_count, 1)
914 self.assertEqual(self.fake_open.last_invocation,
915 ((filename, mode), {}))
916
917 @staticmethod
918 def replace_builtin_open(new_open_func):
Florent Xiclunaa011e2b2011-11-07 19:43:07 +0100919 original_open = builtins.open
920 builtins.open = new_open_func
briancurtin906f0c42011-03-15 10:29:41 -0400921 return original_open
922
923class Test_hook_encoded(unittest.TestCase):
924 """Unit tests for fileinput.hook_encoded()"""
925
926 def test(self):
927 encoding = object()
Serhiy Storchakab2752102016-04-27 23:13:46 +0300928 errors = object()
929 result = fileinput.hook_encoded(encoding, errors=errors)
briancurtin906f0c42011-03-15 10:29:41 -0400930
931 fake_open = InvocationRecorder()
Florent Xiclunaa011e2b2011-11-07 19:43:07 +0100932 original_open = builtins.open
933 builtins.open = fake_open
briancurtin906f0c42011-03-15 10:29:41 -0400934 try:
935 filename = object()
936 mode = object()
937 open_result = result(filename, mode)
938 finally:
Florent Xiclunaa011e2b2011-11-07 19:43:07 +0100939 builtins.open = original_open
briancurtin906f0c42011-03-15 10:29:41 -0400940
941 self.assertEqual(fake_open.invocation_count, 1)
942
Florent Xiclunaa011e2b2011-11-07 19:43:07 +0100943 args, kwargs = fake_open.last_invocation
briancurtin906f0c42011-03-15 10:29:41 -0400944 self.assertIs(args[0], filename)
945 self.assertIs(args[1], mode)
Florent Xiclunaa011e2b2011-11-07 19:43:07 +0100946 self.assertIs(kwargs.pop('encoding'), encoding)
Serhiy Storchakab2752102016-04-27 23:13:46 +0300947 self.assertIs(kwargs.pop('errors'), errors)
Florent Xiclunaa011e2b2011-11-07 19:43:07 +0100948 self.assertFalse(kwargs)
Georg Brandl6cb7b652010-07-31 20:08:15 +0000949
Serhiy Storchakab2752102016-04-27 23:13:46 +0300950 def test_errors(self):
951 with open(TESTFN, 'wb') as f:
952 f.write(b'\x80abc')
953 self.addCleanup(safe_unlink, TESTFN)
954
955 def check(errors, expected_lines):
956 with FileInput(files=TESTFN, mode='r',
957 openhook=hook_encoded('utf-8', errors=errors)) as fi:
958 lines = list(fi)
959 self.assertEqual(lines, expected_lines)
960
961 check('ignore', ['abc'])
962 with self.assertRaises(UnicodeDecodeError):
963 check('strict', ['abc'])
964 check('replace', ['\ufffdabc'])
965 check('backslashreplace', ['\\x80abc'])
966
Serhiy Storchaka517b7472014-02-26 20:59:43 +0200967 def test_modes(self):
Serhiy Storchaka517b7472014-02-26 20:59:43 +0200968 with open(TESTFN, 'wb') as f:
Serhiy Storchaka682ea5f2014-03-03 21:17:17 +0200969 # UTF-7 is a convenient, seldom used encoding
Serhiy Storchaka517b7472014-02-26 20:59:43 +0200970 f.write(b'A\nB\r\nC\rD+IKw-')
971 self.addCleanup(safe_unlink, TESTFN)
972
973 def check(mode, expected_lines):
974 with FileInput(files=TESTFN, mode=mode,
975 openhook=hook_encoded('utf-7')) as fi:
976 lines = list(fi)
977 self.assertEqual(lines, expected_lines)
978
979 check('r', ['A\n', 'B\n', 'C\n', 'D\u20ac'])
Serhiy Storchaka517b7472014-02-26 20:59:43 +0200980 with self.assertRaises(ValueError):
981 check('rb', ['A\n', 'B\r\n', 'C\r', 'D\u20ac'])
982
Guido van Rossumd8faa362007-04-27 19:54:29 +0000983
Martin Panter7978e102016-01-16 06:26:54 +0000984class MiscTest(unittest.TestCase):
985
986 def test_all(self):
Serhiy Storchaka674e2d02016-03-08 18:35:19 +0200987 support.check__all__(self, fileinput)
Martin Panter7978e102016-01-16 06:26:54 +0000988
989
Guido van Rossumd8faa362007-04-27 19:54:29 +0000990if __name__ == "__main__":
Brett Cannon3e9a9ae2013-06-12 21:25:59 -0400991 unittest.main()