blob: 35347185da0484f36d327475eee3165b842996af [file] [log] [blame]
Guido van Rossum7d5b99d1997-11-21 17:12:59 +00001"""Helper class to quickly write a loop over all standard input files.
2
3Typical use is:
4
5 import fileinput
Inada Naoki333d10c2021-04-14 14:12:58 +09006 for line in fileinput.input(encoding="utf-8"):
Guido van Rossum7d5b99d1997-11-21 17:12:59 +00007 process(line)
8
9This iterates over the lines of all files listed in sys.argv[1:],
10defaulting to sys.stdin if the list is empty. If a filename is '-' it
Michele Angrisanoaca273e2019-06-02 23:01:49 +020011is also replaced by sys.stdin and the optional arguments mode and
12openhook are ignored. To specify an alternative list of filenames,
13pass it as the argument to input(). A single file name is also allowed.
Guido van Rossum7d5b99d1997-11-21 17:12:59 +000014
15Functions filename(), lineno() return the filename and cumulative line
16number of the line that has just been read; filelineno() returns its
17line number in the current file; isfirstline() returns true iff the
18line just read is the first line of its file; isstdin() returns true
19iff the line was read from sys.stdin. Function nextfile() closes the
20current file so that the next iteration will read the first line from
21the next file (if any); lines not read from the file will not count
22towards the cumulative line count; the filename is not changed until
23after the first line of the next file has been read. Function close()
24closes the sequence.
25
26Before any lines have been read, filename() returns None and both line
27numbers are zero; nextfile() has no effect. After all lines have been
28read, filename() and the line number functions return the values
29pertaining to the last line read; nextfile() has no effect.
30
Georg Brandlc029f872006-02-19 14:12:34 +000031All files are opened in text mode by default, you can override this by
32setting the mode parameter to input() or FileInput.__init__().
Andrew Svetlovf7a17b42012-12-25 16:47:37 +020033If an I/O error occurs during opening or reading a file, the OSError
Georg Brandlc029f872006-02-19 14:12:34 +000034exception is raised.
Guido van Rossum7d5b99d1997-11-21 17:12:59 +000035
36If sys.stdin is used more than once, the second and further use will
37return no lines, except perhaps for interactive use, or if it has been
38explicitly reset (e.g. using sys.stdin.seek(0)).
39
40Empty files are opened and immediately closed; the only time their
41presence in the list of filenames is noticeable at all is when the
42last file opened is empty.
43
44It is possible that the last line of a file doesn't end in a newline
45character; otherwise lines are returned including the trailing
46newline.
47
48Class FileInput is the implementation; its methods filename(),
49lineno(), fileline(), isfirstline(), isstdin(), nextfile() and close()
50correspond to the functions in the module. In addition it has a
51readline() method which returns the next input line, and a
52__getitem__() method which implements the sequence behavior. The
53sequence must be accessed in strictly sequential order; sequence
54access and readline() cannot be mixed.
55
56Optional in-place filtering: if the keyword argument inplace=1 is
57passed to input() or to the FileInput constructor, the file is moved
58to a backup file and standard output is directed to the input file.
59This makes it possible to write a filter that rewrites its input file
60in place. If the keyword argument backup=".<some extension>" is also
61given, it specifies the extension for the backup file, and the backup
62file remains around; by default, the extension is ".bak" and it is
63deleted when the output file is closed. In-place filtering is
64disabled when standard input is read. XXX The current implementation
65does not work for MS-DOS 8+3 filesystems.
Guido van Rossum7d5b99d1997-11-21 17:12:59 +000066"""
67
Inada Naoki333d10c2021-04-14 14:12:58 +090068import io
Walter Dörwald294bbf32002-06-06 09:48:13 +000069import sys, os
Ethan Smithe3ec44d2020-04-09 21:47:31 -070070from types import GenericAlias
Guido van Rossum7d5b99d1997-11-21 17:12:59 +000071
Georg Brandlef0a8652009-05-17 12:22:57 +000072__all__ = ["input", "close", "nextfile", "filename", "lineno", "filelineno",
Martin Panter7978e102016-01-16 06:26:54 +000073 "fileno", "isfirstline", "isstdin", "FileInput", "hook_compressed",
74 "hook_encoded"]
Skip Montanaroeccd02a2001-01-20 23:34:12 +000075
Guido van Rossum7d5b99d1997-11-21 17:12:59 +000076_state = None
77
Inada Naoki333d10c2021-04-14 14:12:58 +090078def input(files=None, inplace=False, backup="", *, mode="r", openhook=None,
79 encoding=None, errors=None):
Terry Jan Reedy70d2c712013-06-28 18:59:28 -040080 """Return an instance of the FileInput class, which can be iterated.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000081
Terry Jan Reedy70d2c712013-06-28 18:59:28 -040082 The parameters are passed to the constructor of the FileInput class.
83 The returned instance, in addition to being an iterator,
84 keeps global state for the functions of this module,.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000085 """
Guido van Rossum7d5b99d1997-11-21 17:12:59 +000086 global _state
87 if _state and _state._file:
Collin Winterce36ad82007-08-30 01:19:48 +000088 raise RuntimeError("input() already active")
Inada Naoki333d10c2021-04-14 14:12:58 +090089 _state = FileInput(files, inplace, backup, mode=mode, openhook=openhook,
90 encoding=encoding, errors=errors)
Guido van Rossum7d5b99d1997-11-21 17:12:59 +000091 return _state
92
93def close():
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000094 """Close the sequence."""
Guido van Rossum7d5b99d1997-11-21 17:12:59 +000095 global _state
96 state = _state
97 _state = None
98 if state:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000099 state.close()
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000100
101def nextfile():
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000102 """
103 Close the current file so that the next iteration will read the first
104 line from the next file (if any); lines not read from the file will
105 not count towards the cumulative line count. The filename is not
106 changed until after the first line of the next file has been read.
107 Before the first line has been read, this function has no effect;
108 it cannot be used to skip the first file. After the last line of the
Tim Peters8ac14952002-05-23 15:15:30 +0000109 last file has been read, this function has no effect.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000110 """
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000111 if not _state:
Collin Winterce36ad82007-08-30 01:19:48 +0000112 raise RuntimeError("no active input()")
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000113 return _state.nextfile()
114
115def filename():
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000116 """
117 Return the name of the file currently being read.
Tim Peters8ac14952002-05-23 15:15:30 +0000118 Before the first line has been read, returns None.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000119 """
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000120 if not _state:
Collin Winterce36ad82007-08-30 01:19:48 +0000121 raise RuntimeError("no active input()")
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000122 return _state.filename()
123
124def lineno():
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000125 """
126 Return the cumulative line number of the line that has just been read.
127 Before the first line has been read, returns 0. After the last line
Tim Peters8ac14952002-05-23 15:15:30 +0000128 of the last file has been read, returns the line number of that line.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000129 """
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000130 if not _state:
Collin Winterce36ad82007-08-30 01:19:48 +0000131 raise RuntimeError("no active input()")
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000132 return _state.lineno()
133
134def filelineno():
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000135 """
136 Return the line number in the current file. Before the first line
137 has been read, returns 0. After the last line of the last file has
Tim Peters8ac14952002-05-23 15:15:30 +0000138 been read, returns the line number of that line within the file.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000139 """
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000140 if not _state:
Collin Winterce36ad82007-08-30 01:19:48 +0000141 raise RuntimeError("no active input()")
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000142 return _state.filelineno()
143
Georg Brandl67e9fb92006-02-19 13:56:17 +0000144def fileno():
145 """
146 Return the file number of the current file. When no file is currently
147 opened, returns -1.
148 """
149 if not _state:
Collin Winterce36ad82007-08-30 01:19:48 +0000150 raise RuntimeError("no active input()")
Georg Brandl67e9fb92006-02-19 13:56:17 +0000151 return _state.fileno()
152
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000153def isfirstline():
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000154 """
155 Returns true the line just read is the first line of its file,
Tim Peters8ac14952002-05-23 15:15:30 +0000156 otherwise returns false.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000157 """
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000158 if not _state:
Collin Winterce36ad82007-08-30 01:19:48 +0000159 raise RuntimeError("no active input()")
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000160 return _state.isfirstline()
161
162def isstdin():
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000163 """
164 Returns true if the last line was read from sys.stdin,
Tim Peters8ac14952002-05-23 15:15:30 +0000165 otherwise returns false.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000166 """
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000167 if not _state:
Collin Winterce36ad82007-08-30 01:19:48 +0000168 raise RuntimeError("no active input()")
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000169 return _state.isstdin()
170
171class FileInput:
Matthias Bussonnier1a3faf92019-05-20 13:44:11 -0700172 """FileInput([files[, inplace[, backup]]], *, mode=None, openhook=None)
Tim Peters8ac14952002-05-23 15:15:30 +0000173
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000174 Class FileInput is the implementation of the module; its methods
Georg Brandl67e9fb92006-02-19 13:56:17 +0000175 filename(), lineno(), fileline(), isfirstline(), isstdin(), fileno(),
176 nextfile() and close() correspond to the functions of the same name
177 in the module.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000178 In addition it has a readline() method which returns the next
179 input line, and a __getitem__() method which implements the
180 sequence behavior. The sequence must be accessed in strictly
Tim Peters8ac14952002-05-23 15:15:30 +0000181 sequential order; random access and readline() cannot be mixed.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000182 """
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000183
Matthias Bussonnier1a3faf92019-05-20 13:44:11 -0700184 def __init__(self, files=None, inplace=False, backup="", *,
Inada Naoki333d10c2021-04-14 14:12:58 +0900185 mode="r", openhook=None, encoding=None, errors=None):
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000186 if isinstance(files, str):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000187 files = (files,)
Roy Williams002665a2017-05-22 22:24:17 -0700188 elif isinstance(files, os.PathLike):
189 files = (os.fspath(files), )
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000190 else:
Guido van Rossum2516b392000-04-10 17:16:12 +0000191 if files is None:
192 files = sys.argv[1:]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000193 if not files:
Guido van Rossum2516b392000-04-10 17:16:12 +0000194 files = ('-',)
195 else:
196 files = tuple(files)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000197 self._files = files
198 self._inplace = inplace
199 self._backup = backup
200 self._savestdout = None
201 self._output = None
202 self._filename = None
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200203 self._startlineno = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000204 self._filelineno = 0
205 self._file = None
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000206 self._isstdin = False
Guido van Rossum0aec9fb1998-07-20 15:49:28 +0000207 self._backupfilename = None
Inada Naoki333d10c2021-04-14 14:12:58 +0900208 self._encoding = encoding
209 self._errors = errors
210
211 # We can not use io.text_encoding() here because old openhook doesn't
212 # take encoding parameter.
Inada Naoki878bc8b2021-04-27 15:47:16 +0900213 if (sys.flags.warn_default_encoding and
214 "b" not in mode and encoding is None and openhook is None):
Inada Naoki333d10c2021-04-14 14:12:58 +0900215 import warnings
216 warnings.warn("'encoding' argument not specified.",
217 EncodingWarning, 2)
218
Georg Brandlc029f872006-02-19 14:12:34 +0000219 # restrict mode argument to reading modes
Victor Stinner942f7a22020-03-04 18:50:22 +0100220 if mode not in ('r', 'rU', 'U', 'rb'):
221 raise ValueError("FileInput opening mode must be one of "
222 "'r', 'rU', 'U' and 'rb'")
223 if 'U' in mode:
224 import warnings
225 warnings.warn("'U' mode is deprecated",
226 DeprecationWarning, 2)
Georg Brandlc029f872006-02-19 14:12:34 +0000227 self._mode = mode
Victor Stinner942f7a22020-03-04 18:50:22 +0100228 self._write_mode = mode.replace('r', 'w') if 'U' not in mode else 'w'
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200229 if openhook:
230 if inplace:
231 raise ValueError("FileInput cannot use an opening hook in inplace mode")
232 if not callable(openhook):
233 raise ValueError("FileInput openhook must be callable")
Georg Brandlc98eeed2006-02-19 14:57:47 +0000234 self._openhook = openhook
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000235
236 def __del__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000237 self.close()
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000238
239 def close(self):
Serhiy Storchaka7e7a3db2015-04-10 13:24:41 +0300240 try:
241 self.nextfile()
242 finally:
243 self._files = ()
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000244
Georg Brandl6cb7b652010-07-31 20:08:15 +0000245 def __enter__(self):
246 return self
247
248 def __exit__(self, type, value, traceback):
249 self.close()
250
Neil Schemenauer908632a2002-03-26 20:28:40 +0000251 def __iter__(self):
252 return self
253
Georg Brandla18af4e2007-04-21 15:47:16 +0000254 def __next__(self):
Serhiy Storchaka0554d832016-03-08 23:35:35 +0200255 while True:
256 line = self._readline()
257 if line:
258 self._filelineno += 1
259 return line
260 if not self._file:
261 raise StopIteration
262 self.nextfile()
263 # repeat with next file
Tim Peters863ac442002-04-16 01:38:40 +0000264
Neil Schemenauer908632a2002-03-26 20:28:40 +0000265 def __getitem__(self, i):
Berker Peksag84a13fb2018-08-11 09:05:04 +0300266 import warnings
267 warnings.warn(
268 "Support for indexing FileInput objects is deprecated. "
269 "Use iterator protocol instead.",
270 DeprecationWarning,
271 stacklevel=2
272 )
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200273 if i != self.lineno():
Collin Winterce36ad82007-08-30 01:19:48 +0000274 raise RuntimeError("accessing lines out of order")
Neil Schemenauer908632a2002-03-26 20:28:40 +0000275 try:
Georg Brandla18af4e2007-04-21 15:47:16 +0000276 return self.__next__()
Neil Schemenauer908632a2002-03-26 20:28:40 +0000277 except StopIteration:
Collin Winterce36ad82007-08-30 01:19:48 +0000278 raise IndexError("end of input reached")
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000279
280 def nextfile(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000281 savestdout = self._savestdout
Serhiy Storchaka2116b122015-04-10 13:29:28 +0300282 self._savestdout = None
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000283 if savestdout:
284 sys.stdout = savestdout
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000285
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000286 output = self._output
Serhiy Storchaka2116b122015-04-10 13:29:28 +0300287 self._output = None
Serhiy Storchaka7e7a3db2015-04-10 13:24:41 +0300288 try:
289 if output:
290 output.close()
291 finally:
292 file = self._file
Serhiy Storchaka2116b122015-04-10 13:29:28 +0300293 self._file = None
Serhiy Storchaka0554d832016-03-08 23:35:35 +0200294 try:
295 del self._readline # restore FileInput._readline
296 except AttributeError:
297 pass
Serhiy Storchaka7e7a3db2015-04-10 13:24:41 +0300298 try:
299 if file and not self._isstdin:
300 file.close()
301 finally:
302 backupfilename = self._backupfilename
Serhiy Storchaka2116b122015-04-10 13:29:28 +0300303 self._backupfilename = None
Serhiy Storchaka7e7a3db2015-04-10 13:24:41 +0300304 if backupfilename and not self._backup:
305 try: os.unlink(backupfilename)
306 except OSError: pass
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000307
Serhiy Storchaka7e7a3db2015-04-10 13:24:41 +0300308 self._isstdin = False
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000309
310 def readline(self):
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200311 while True:
312 line = self._readline()
313 if line:
314 self._filelineno += 1
315 return line
316 if not self._file:
317 return line
318 self.nextfile()
319 # repeat with next file
320
Serhiy Storchaka0554d832016-03-08 23:35:35 +0200321 def _readline(self):
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200322 if not self._files:
323 if 'b' in self._mode:
324 return b''
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000325 else:
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200326 return ''
327 self._filename = self._files[0]
328 self._files = self._files[1:]
329 self._startlineno = self.lineno()
330 self._filelineno = 0
331 self._file = None
332 self._isstdin = False
333 self._backupfilename = 0
Inada Naoki878bc8b2021-04-27 15:47:16 +0900334
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
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200341 if self._filename == '-':
342 self._filename = '<stdin>'
343 if 'b' in self._mode:
344 self._file = getattr(sys.stdin, 'buffer', sys.stdin)
345 else:
346 self._file = sys.stdin
347 self._isstdin = True
348 else:
349 if self._inplace:
350 self._backupfilename = (
Zhiming Wang06de1ae2017-09-05 01:37:24 +0800351 os.fspath(self._filename) + (self._backup or ".bak"))
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200352 try:
353 os.unlink(self._backupfilename)
354 except OSError:
355 pass
356 # The next few lines may raise OSError
357 os.rename(self._filename, self._backupfilename)
Inada Naoki878bc8b2021-04-27 15:47:16 +0900358 self._file = open(self._backupfilename, self._mode, encoding=encoding)
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200359 try:
360 perm = os.fstat(self._file.fileno()).st_mode
361 except OSError:
Inada Naoki878bc8b2021-04-27 15:47:16 +0900362 self._output = open(self._filename, self._write_mode, encoding=encoding)
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200363 else:
364 mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC
365 if hasattr(os, 'O_BINARY'):
366 mode |= os.O_BINARY
367
368 fd = os.open(self._filename, mode, perm)
Inada Naoki878bc8b2021-04-27 15:47:16 +0900369 self._output = os.fdopen(fd, self._write_mode, encoding=encoding)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200370 try:
Anthony Sottile8377cd42019-02-25 14:32:27 -0800371 os.chmod(self._filename, perm)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200372 except OSError:
373 pass
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200374 self._savestdout = sys.stdout
375 sys.stdout = self._output
376 else:
377 # This may raise OSError
378 if self._openhook:
Inada Naoki333d10c2021-04-14 14:12:58 +0900379 # Custom hooks made previous to Python 3.10 didn't have
380 # encoding argument
381 if self._encoding is None:
382 self._file = self._openhook(self._filename, self._mode)
383 else:
384 self._file = self._openhook(
385 self._filename, self._mode, encoding=self._encoding, errors=self._errors)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000386 else:
Inada Naoki333d10c2021-04-14 14:12:58 +0900387 self._file = open(self._filename, self._mode, encoding=encoding, errors=self._errors)
Serhiy Storchaka0554d832016-03-08 23:35:35 +0200388 self._readline = self._file.readline # hide FileInput._readline
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200389 return self._readline()
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000390
391 def filename(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000392 return self._filename
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000393
394 def lineno(self):
Serhiy Storchakacc2dbc52016-03-08 18:28:36 +0200395 return self._startlineno + self._filelineno
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000396
397 def filelineno(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000398 return self._filelineno
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000399
Georg Brandl67e9fb92006-02-19 13:56:17 +0000400 def fileno(self):
401 if self._file:
402 try:
403 return self._file.fileno()
404 except ValueError:
405 return -1
406 else:
407 return -1
408
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000409 def isfirstline(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000410 return self._filelineno == 1
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000411
412 def isstdin(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000413 return self._isstdin
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000414
Ethan Smithe3ec44d2020-04-09 21:47:31 -0700415 __class_getitem__ = classmethod(GenericAlias)
416
Georg Brandlc98eeed2006-02-19 14:57:47 +0000417
Inada Naoki333d10c2021-04-14 14:12:58 +0900418def hook_compressed(filename, mode, *, encoding=None, errors=None):
419 if encoding is None: # EncodingWarning is emitted in FileInput() already.
420 encoding = "locale"
Georg Brandlc98eeed2006-02-19 14:57:47 +0000421 ext = os.path.splitext(filename)[1]
422 if ext == '.gz':
423 import gzip
Inada Naoki333d10c2021-04-14 14:12:58 +0900424 stream = gzip.open(filename, mode)
Georg Brandlc98eeed2006-02-19 14:57:47 +0000425 elif ext == '.bz2':
426 import bz2
Inada Naoki333d10c2021-04-14 14:12:58 +0900427 stream = bz2.BZ2File(filename, mode)
Georg Brandlc98eeed2006-02-19 14:57:47 +0000428 else:
Inada Naoki333d10c2021-04-14 14:12:58 +0900429 return open(filename, mode, encoding=encoding, errors=errors)
430
431 # gzip and bz2 are binary mode by default.
432 if "b" not in mode:
433 stream = io.TextIOWrapper(stream, encoding=encoding, errors=errors)
434 return stream
Georg Brandlc98eeed2006-02-19 14:57:47 +0000435
436
Serhiy Storchakab2752102016-04-27 23:13:46 +0300437def hook_encoded(encoding, errors=None):
Georg Brandlc98eeed2006-02-19 14:57:47 +0000438 def openhook(filename, mode):
Serhiy Storchakab2752102016-04-27 23:13:46 +0300439 return open(filename, mode, encoding=encoding, errors=errors)
Georg Brandlc98eeed2006-02-19 14:57:47 +0000440 return openhook
441
442
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000443def _test():
444 import getopt
Georg Brandlef0a8652009-05-17 12:22:57 +0000445 inplace = False
446 backup = False
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000447 opts, args = getopt.getopt(sys.argv[1:], "ib:")
448 for o, a in opts:
Georg Brandlef0a8652009-05-17 12:22:57 +0000449 if o == '-i': inplace = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000450 if o == '-b': backup = a
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000451 for line in input(args, inplace=inplace, backup=backup):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000452 if line[-1:] == '\n': line = line[:-1]
453 if line[-1:] == '\r': line = line[:-1]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000454 print("%d: %s[%d]%s %s" % (lineno(), filename(), filelineno(),
455 isfirstline() and "*" or "", line))
456 print("%d: %s[%d]" % (lineno(), filename(), filelineno()))
Guido van Rossum7d5b99d1997-11-21 17:12:59 +0000457
458if __name__ == '__main__':
459 _test()