xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/fileinput.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""Helper class to quickly write a loop over all standard input files.
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard WorkerTypical use is:
4*cda5da8dSAndroid Build Coastguard Worker
5*cda5da8dSAndroid Build Coastguard Worker    import fileinput
6*cda5da8dSAndroid Build Coastguard Worker    for line in fileinput.input(encoding="utf-8"):
7*cda5da8dSAndroid Build Coastguard Worker        process(line)
8*cda5da8dSAndroid Build Coastguard Worker
9*cda5da8dSAndroid Build Coastguard WorkerThis iterates over the lines of all files listed in sys.argv[1:],
10*cda5da8dSAndroid Build Coastguard Workerdefaulting to sys.stdin if the list is empty.  If a filename is '-' it
11*cda5da8dSAndroid Build Coastguard Workeris also replaced by sys.stdin and the optional arguments mode and
12*cda5da8dSAndroid Build Coastguard Workeropenhook are ignored.  To specify an alternative list of filenames,
13*cda5da8dSAndroid Build Coastguard Workerpass it as the argument to input().  A single file name is also allowed.
14*cda5da8dSAndroid Build Coastguard Worker
15*cda5da8dSAndroid Build Coastguard WorkerFunctions filename(), lineno() return the filename and cumulative line
16*cda5da8dSAndroid Build Coastguard Workernumber of the line that has just been read; filelineno() returns its
17*cda5da8dSAndroid Build Coastguard Workerline number in the current file; isfirstline() returns true iff the
18*cda5da8dSAndroid Build Coastguard Workerline just read is the first line of its file; isstdin() returns true
19*cda5da8dSAndroid Build Coastguard Workeriff the line was read from sys.stdin.  Function nextfile() closes the
20*cda5da8dSAndroid Build Coastguard Workercurrent file so that the next iteration will read the first line from
21*cda5da8dSAndroid Build Coastguard Workerthe next file (if any); lines not read from the file will not count
22*cda5da8dSAndroid Build Coastguard Workertowards the cumulative line count; the filename is not changed until
23*cda5da8dSAndroid Build Coastguard Workerafter the first line of the next file has been read.  Function close()
24*cda5da8dSAndroid Build Coastguard Workercloses the sequence.
25*cda5da8dSAndroid Build Coastguard Worker
26*cda5da8dSAndroid Build Coastguard WorkerBefore any lines have been read, filename() returns None and both line
27*cda5da8dSAndroid Build Coastguard Workernumbers are zero; nextfile() has no effect.  After all lines have been
28*cda5da8dSAndroid Build Coastguard Workerread, filename() and the line number functions return the values
29*cda5da8dSAndroid Build Coastguard Workerpertaining to the last line read; nextfile() has no effect.
30*cda5da8dSAndroid Build Coastguard Worker
31*cda5da8dSAndroid Build Coastguard WorkerAll files are opened in text mode by default, you can override this by
32*cda5da8dSAndroid Build Coastguard Workersetting the mode parameter to input() or FileInput.__init__().
33*cda5da8dSAndroid Build Coastguard WorkerIf an I/O error occurs during opening or reading a file, the OSError
34*cda5da8dSAndroid Build Coastguard Workerexception is raised.
35*cda5da8dSAndroid Build Coastguard Worker
36*cda5da8dSAndroid Build Coastguard WorkerIf sys.stdin is used more than once, the second and further use will
37*cda5da8dSAndroid Build Coastguard Workerreturn no lines, except perhaps for interactive use, or if it has been
38*cda5da8dSAndroid Build Coastguard Workerexplicitly reset (e.g. using sys.stdin.seek(0)).
39*cda5da8dSAndroid Build Coastguard Worker
40*cda5da8dSAndroid Build Coastguard WorkerEmpty files are opened and immediately closed; the only time their
41*cda5da8dSAndroid Build Coastguard Workerpresence in the list of filenames is noticeable at all is when the
42*cda5da8dSAndroid Build Coastguard Workerlast file opened is empty.
43*cda5da8dSAndroid Build Coastguard Worker
44*cda5da8dSAndroid Build Coastguard WorkerIt is possible that the last line of a file doesn't end in a newline
45*cda5da8dSAndroid Build Coastguard Workercharacter; otherwise lines are returned including the trailing
46*cda5da8dSAndroid Build Coastguard Workernewline.
47*cda5da8dSAndroid Build Coastguard Worker
48*cda5da8dSAndroid Build Coastguard WorkerClass FileInput is the implementation; its methods filename(),
49*cda5da8dSAndroid Build Coastguard Workerlineno(), fileline(), isfirstline(), isstdin(), nextfile() and close()
50*cda5da8dSAndroid Build Coastguard Workercorrespond to the functions in the module.  In addition it has a
51*cda5da8dSAndroid Build Coastguard Workerreadline() method which returns the next input line, and a
52*cda5da8dSAndroid Build Coastguard Worker__getitem__() method which implements the sequence behavior.  The
53*cda5da8dSAndroid Build Coastguard Workersequence must be accessed in strictly sequential order; sequence
54*cda5da8dSAndroid Build Coastguard Workeraccess and readline() cannot be mixed.
55*cda5da8dSAndroid Build Coastguard Worker
56*cda5da8dSAndroid Build Coastguard WorkerOptional in-place filtering: if the keyword argument inplace=1 is
57*cda5da8dSAndroid Build Coastguard Workerpassed to input() or to the FileInput constructor, the file is moved
58*cda5da8dSAndroid Build Coastguard Workerto a backup file and standard output is directed to the input file.
59*cda5da8dSAndroid Build Coastguard WorkerThis makes it possible to write a filter that rewrites its input file
60*cda5da8dSAndroid Build Coastguard Workerin place.  If the keyword argument backup=".<some extension>" is also
61*cda5da8dSAndroid Build Coastguard Workergiven, it specifies the extension for the backup file, and the backup
62*cda5da8dSAndroid Build Coastguard Workerfile remains around; by default, the extension is ".bak" and it is
63*cda5da8dSAndroid Build Coastguard Workerdeleted when the output file is closed.  In-place filtering is
64*cda5da8dSAndroid Build Coastguard Workerdisabled when standard input is read.  XXX The current implementation
65*cda5da8dSAndroid Build Coastguard Workerdoes not work for MS-DOS 8+3 filesystems.
66*cda5da8dSAndroid Build Coastguard Worker"""
67*cda5da8dSAndroid Build Coastguard Worker
68*cda5da8dSAndroid Build Coastguard Workerimport io
69*cda5da8dSAndroid Build Coastguard Workerimport sys, os
70*cda5da8dSAndroid Build Coastguard Workerfrom types import GenericAlias
71*cda5da8dSAndroid Build Coastguard Worker
72*cda5da8dSAndroid Build Coastguard Worker__all__ = ["input", "close", "nextfile", "filename", "lineno", "filelineno",
73*cda5da8dSAndroid Build Coastguard Worker           "fileno", "isfirstline", "isstdin", "FileInput", "hook_compressed",
74*cda5da8dSAndroid Build Coastguard Worker           "hook_encoded"]
75*cda5da8dSAndroid Build Coastguard Worker
76*cda5da8dSAndroid Build Coastguard Worker_state = None
77*cda5da8dSAndroid Build Coastguard Worker
78*cda5da8dSAndroid Build Coastguard Workerdef input(files=None, inplace=False, backup="", *, mode="r", openhook=None,
79*cda5da8dSAndroid Build Coastguard Worker          encoding=None, errors=None):
80*cda5da8dSAndroid Build Coastguard Worker    """Return an instance of the FileInput class, which can be iterated.
81*cda5da8dSAndroid Build Coastguard Worker
82*cda5da8dSAndroid Build Coastguard Worker    The parameters are passed to the constructor of the FileInput class.
83*cda5da8dSAndroid Build Coastguard Worker    The returned instance, in addition to being an iterator,
84*cda5da8dSAndroid Build Coastguard Worker    keeps global state for the functions of this module,.
85*cda5da8dSAndroid Build Coastguard Worker    """
86*cda5da8dSAndroid Build Coastguard Worker    global _state
87*cda5da8dSAndroid Build Coastguard Worker    if _state and _state._file:
88*cda5da8dSAndroid Build Coastguard Worker        raise RuntimeError("input() already active")
89*cda5da8dSAndroid Build Coastguard Worker    _state = FileInput(files, inplace, backup, mode=mode, openhook=openhook,
90*cda5da8dSAndroid Build Coastguard Worker                       encoding=encoding, errors=errors)
91*cda5da8dSAndroid Build Coastguard Worker    return _state
92*cda5da8dSAndroid Build Coastguard Worker
93*cda5da8dSAndroid Build Coastguard Workerdef close():
94*cda5da8dSAndroid Build Coastguard Worker    """Close the sequence."""
95*cda5da8dSAndroid Build Coastguard Worker    global _state
96*cda5da8dSAndroid Build Coastguard Worker    state = _state
97*cda5da8dSAndroid Build Coastguard Worker    _state = None
98*cda5da8dSAndroid Build Coastguard Worker    if state:
99*cda5da8dSAndroid Build Coastguard Worker        state.close()
100*cda5da8dSAndroid Build Coastguard Worker
101*cda5da8dSAndroid Build Coastguard Workerdef nextfile():
102*cda5da8dSAndroid Build Coastguard Worker    """
103*cda5da8dSAndroid Build Coastguard Worker    Close the current file so that the next iteration will read the first
104*cda5da8dSAndroid Build Coastguard Worker    line from the next file (if any); lines not read from the file will
105*cda5da8dSAndroid Build Coastguard Worker    not count towards the cumulative line count. The filename is not
106*cda5da8dSAndroid Build Coastguard Worker    changed until after the first line of the next file has been read.
107*cda5da8dSAndroid Build Coastguard Worker    Before the first line has been read, this function has no effect;
108*cda5da8dSAndroid Build Coastguard Worker    it cannot be used to skip the first file. After the last line of the
109*cda5da8dSAndroid Build Coastguard Worker    last file has been read, this function has no effect.
110*cda5da8dSAndroid Build Coastguard Worker    """
111*cda5da8dSAndroid Build Coastguard Worker    if not _state:
112*cda5da8dSAndroid Build Coastguard Worker        raise RuntimeError("no active input()")
113*cda5da8dSAndroid Build Coastguard Worker    return _state.nextfile()
114*cda5da8dSAndroid Build Coastguard Worker
115*cda5da8dSAndroid Build Coastguard Workerdef filename():
116*cda5da8dSAndroid Build Coastguard Worker    """
117*cda5da8dSAndroid Build Coastguard Worker    Return the name of the file currently being read.
118*cda5da8dSAndroid Build Coastguard Worker    Before the first line has been read, returns None.
119*cda5da8dSAndroid Build Coastguard Worker    """
120*cda5da8dSAndroid Build Coastguard Worker    if not _state:
121*cda5da8dSAndroid Build Coastguard Worker        raise RuntimeError("no active input()")
122*cda5da8dSAndroid Build Coastguard Worker    return _state.filename()
123*cda5da8dSAndroid Build Coastguard Worker
124*cda5da8dSAndroid Build Coastguard Workerdef lineno():
125*cda5da8dSAndroid Build Coastguard Worker    """
126*cda5da8dSAndroid Build Coastguard Worker    Return the cumulative line number of the line that has just been read.
127*cda5da8dSAndroid Build Coastguard Worker    Before the first line has been read, returns 0. After the last line
128*cda5da8dSAndroid Build Coastguard Worker    of the last file has been read, returns the line number of that line.
129*cda5da8dSAndroid Build Coastguard Worker    """
130*cda5da8dSAndroid Build Coastguard Worker    if not _state:
131*cda5da8dSAndroid Build Coastguard Worker        raise RuntimeError("no active input()")
132*cda5da8dSAndroid Build Coastguard Worker    return _state.lineno()
133*cda5da8dSAndroid Build Coastguard Worker
134*cda5da8dSAndroid Build Coastguard Workerdef filelineno():
135*cda5da8dSAndroid Build Coastguard Worker    """
136*cda5da8dSAndroid Build Coastguard Worker    Return the line number in the current file. Before the first line
137*cda5da8dSAndroid Build Coastguard Worker    has been read, returns 0. After the last line of the last file has
138*cda5da8dSAndroid Build Coastguard Worker    been read, returns the line number of that line within the file.
139*cda5da8dSAndroid Build Coastguard Worker    """
140*cda5da8dSAndroid Build Coastguard Worker    if not _state:
141*cda5da8dSAndroid Build Coastguard Worker        raise RuntimeError("no active input()")
142*cda5da8dSAndroid Build Coastguard Worker    return _state.filelineno()
143*cda5da8dSAndroid Build Coastguard Worker
144*cda5da8dSAndroid Build Coastguard Workerdef fileno():
145*cda5da8dSAndroid Build Coastguard Worker    """
146*cda5da8dSAndroid Build Coastguard Worker    Return the file number of the current file. When no file is currently
147*cda5da8dSAndroid Build Coastguard Worker    opened, returns -1.
148*cda5da8dSAndroid Build Coastguard Worker    """
149*cda5da8dSAndroid Build Coastguard Worker    if not _state:
150*cda5da8dSAndroid Build Coastguard Worker        raise RuntimeError("no active input()")
151*cda5da8dSAndroid Build Coastguard Worker    return _state.fileno()
152*cda5da8dSAndroid Build Coastguard Worker
153*cda5da8dSAndroid Build Coastguard Workerdef isfirstline():
154*cda5da8dSAndroid Build Coastguard Worker    """
155*cda5da8dSAndroid Build Coastguard Worker    Returns true the line just read is the first line of its file,
156*cda5da8dSAndroid Build Coastguard Worker    otherwise returns false.
157*cda5da8dSAndroid Build Coastguard Worker    """
158*cda5da8dSAndroid Build Coastguard Worker    if not _state:
159*cda5da8dSAndroid Build Coastguard Worker        raise RuntimeError("no active input()")
160*cda5da8dSAndroid Build Coastguard Worker    return _state.isfirstline()
161*cda5da8dSAndroid Build Coastguard Worker
162*cda5da8dSAndroid Build Coastguard Workerdef isstdin():
163*cda5da8dSAndroid Build Coastguard Worker    """
164*cda5da8dSAndroid Build Coastguard Worker    Returns true if the last line was read from sys.stdin,
165*cda5da8dSAndroid Build Coastguard Worker    otherwise returns false.
166*cda5da8dSAndroid Build Coastguard Worker    """
167*cda5da8dSAndroid Build Coastguard Worker    if not _state:
168*cda5da8dSAndroid Build Coastguard Worker        raise RuntimeError("no active input()")
169*cda5da8dSAndroid Build Coastguard Worker    return _state.isstdin()
170*cda5da8dSAndroid Build Coastguard Worker
171*cda5da8dSAndroid Build Coastguard Workerclass FileInput:
172*cda5da8dSAndroid Build Coastguard Worker    """FileInput([files[, inplace[, backup]]], *, mode=None, openhook=None)
173*cda5da8dSAndroid Build Coastguard Worker
174*cda5da8dSAndroid Build Coastguard Worker    Class FileInput is the implementation of the module; its methods
175*cda5da8dSAndroid Build Coastguard Worker    filename(), lineno(), fileline(), isfirstline(), isstdin(), fileno(),
176*cda5da8dSAndroid Build Coastguard Worker    nextfile() and close() correspond to the functions of the same name
177*cda5da8dSAndroid Build Coastguard Worker    in the module.
178*cda5da8dSAndroid Build Coastguard Worker    In addition it has a readline() method which returns the next
179*cda5da8dSAndroid Build Coastguard Worker    input line, and a __getitem__() method which implements the
180*cda5da8dSAndroid Build Coastguard Worker    sequence behavior. The sequence must be accessed in strictly
181*cda5da8dSAndroid Build Coastguard Worker    sequential order; random access and readline() cannot be mixed.
182*cda5da8dSAndroid Build Coastguard Worker    """
183*cda5da8dSAndroid Build Coastguard Worker
184*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, files=None, inplace=False, backup="", *,
185*cda5da8dSAndroid Build Coastguard Worker                 mode="r", openhook=None, encoding=None, errors=None):
186*cda5da8dSAndroid Build Coastguard Worker        if isinstance(files, str):
187*cda5da8dSAndroid Build Coastguard Worker            files = (files,)
188*cda5da8dSAndroid Build Coastguard Worker        elif isinstance(files, os.PathLike):
189*cda5da8dSAndroid Build Coastguard Worker            files = (os.fspath(files), )
190*cda5da8dSAndroid Build Coastguard Worker        else:
191*cda5da8dSAndroid Build Coastguard Worker            if files is None:
192*cda5da8dSAndroid Build Coastguard Worker                files = sys.argv[1:]
193*cda5da8dSAndroid Build Coastguard Worker            if not files:
194*cda5da8dSAndroid Build Coastguard Worker                files = ('-',)
195*cda5da8dSAndroid Build Coastguard Worker            else:
196*cda5da8dSAndroid Build Coastguard Worker                files = tuple(files)
197*cda5da8dSAndroid Build Coastguard Worker        self._files = files
198*cda5da8dSAndroid Build Coastguard Worker        self._inplace = inplace
199*cda5da8dSAndroid Build Coastguard Worker        self._backup = backup
200*cda5da8dSAndroid Build Coastguard Worker        self._savestdout = None
201*cda5da8dSAndroid Build Coastguard Worker        self._output = None
202*cda5da8dSAndroid Build Coastguard Worker        self._filename = None
203*cda5da8dSAndroid Build Coastguard Worker        self._startlineno = 0
204*cda5da8dSAndroid Build Coastguard Worker        self._filelineno = 0
205*cda5da8dSAndroid Build Coastguard Worker        self._file = None
206*cda5da8dSAndroid Build Coastguard Worker        self._isstdin = False
207*cda5da8dSAndroid Build Coastguard Worker        self._backupfilename = None
208*cda5da8dSAndroid Build Coastguard Worker        self._encoding = encoding
209*cda5da8dSAndroid Build Coastguard Worker        self._errors = errors
210*cda5da8dSAndroid Build Coastguard Worker
211*cda5da8dSAndroid Build Coastguard Worker        # We can not use io.text_encoding() here because old openhook doesn't
212*cda5da8dSAndroid Build Coastguard Worker        # take encoding parameter.
213*cda5da8dSAndroid Build Coastguard Worker        if (sys.flags.warn_default_encoding and
214*cda5da8dSAndroid Build Coastguard Worker                "b" not in mode and encoding is None and openhook is None):
215*cda5da8dSAndroid Build Coastguard Worker            import warnings
216*cda5da8dSAndroid Build Coastguard Worker            warnings.warn("'encoding' argument not specified.",
217*cda5da8dSAndroid Build Coastguard Worker                          EncodingWarning, 2)
218*cda5da8dSAndroid Build Coastguard Worker
219*cda5da8dSAndroid Build Coastguard Worker        # restrict mode argument to reading modes
220*cda5da8dSAndroid Build Coastguard Worker        if mode not in ('r', 'rb'):
221*cda5da8dSAndroid Build Coastguard Worker            raise ValueError("FileInput opening mode must be 'r' or 'rb'")
222*cda5da8dSAndroid Build Coastguard Worker        self._mode = mode
223*cda5da8dSAndroid Build Coastguard Worker        self._write_mode = mode.replace('r', 'w')
224*cda5da8dSAndroid Build Coastguard Worker        if openhook:
225*cda5da8dSAndroid Build Coastguard Worker            if inplace:
226*cda5da8dSAndroid Build Coastguard Worker                raise ValueError("FileInput cannot use an opening hook in inplace mode")
227*cda5da8dSAndroid Build Coastguard Worker            if not callable(openhook):
228*cda5da8dSAndroid Build Coastguard Worker                raise ValueError("FileInput openhook must be callable")
229*cda5da8dSAndroid Build Coastguard Worker        self._openhook = openhook
230*cda5da8dSAndroid Build Coastguard Worker
231*cda5da8dSAndroid Build Coastguard Worker    def __del__(self):
232*cda5da8dSAndroid Build Coastguard Worker        self.close()
233*cda5da8dSAndroid Build Coastguard Worker
234*cda5da8dSAndroid Build Coastguard Worker    def close(self):
235*cda5da8dSAndroid Build Coastguard Worker        try:
236*cda5da8dSAndroid Build Coastguard Worker            self.nextfile()
237*cda5da8dSAndroid Build Coastguard Worker        finally:
238*cda5da8dSAndroid Build Coastguard Worker            self._files = ()
239*cda5da8dSAndroid Build Coastguard Worker
240*cda5da8dSAndroid Build Coastguard Worker    def __enter__(self):
241*cda5da8dSAndroid Build Coastguard Worker        return self
242*cda5da8dSAndroid Build Coastguard Worker
243*cda5da8dSAndroid Build Coastguard Worker    def __exit__(self, type, value, traceback):
244*cda5da8dSAndroid Build Coastguard Worker        self.close()
245*cda5da8dSAndroid Build Coastguard Worker
246*cda5da8dSAndroid Build Coastguard Worker    def __iter__(self):
247*cda5da8dSAndroid Build Coastguard Worker        return self
248*cda5da8dSAndroid Build Coastguard Worker
249*cda5da8dSAndroid Build Coastguard Worker    def __next__(self):
250*cda5da8dSAndroid Build Coastguard Worker        while True:
251*cda5da8dSAndroid Build Coastguard Worker            line = self._readline()
252*cda5da8dSAndroid Build Coastguard Worker            if line:
253*cda5da8dSAndroid Build Coastguard Worker                self._filelineno += 1
254*cda5da8dSAndroid Build Coastguard Worker                return line
255*cda5da8dSAndroid Build Coastguard Worker            if not self._file:
256*cda5da8dSAndroid Build Coastguard Worker                raise StopIteration
257*cda5da8dSAndroid Build Coastguard Worker            self.nextfile()
258*cda5da8dSAndroid Build Coastguard Worker            # repeat with next file
259*cda5da8dSAndroid Build Coastguard Worker
260*cda5da8dSAndroid Build Coastguard Worker    def nextfile(self):
261*cda5da8dSAndroid Build Coastguard Worker        savestdout = self._savestdout
262*cda5da8dSAndroid Build Coastguard Worker        self._savestdout = None
263*cda5da8dSAndroid Build Coastguard Worker        if savestdout:
264*cda5da8dSAndroid Build Coastguard Worker            sys.stdout = savestdout
265*cda5da8dSAndroid Build Coastguard Worker
266*cda5da8dSAndroid Build Coastguard Worker        output = self._output
267*cda5da8dSAndroid Build Coastguard Worker        self._output = None
268*cda5da8dSAndroid Build Coastguard Worker        try:
269*cda5da8dSAndroid Build Coastguard Worker            if output:
270*cda5da8dSAndroid Build Coastguard Worker                output.close()
271*cda5da8dSAndroid Build Coastguard Worker        finally:
272*cda5da8dSAndroid Build Coastguard Worker            file = self._file
273*cda5da8dSAndroid Build Coastguard Worker            self._file = None
274*cda5da8dSAndroid Build Coastguard Worker            try:
275*cda5da8dSAndroid Build Coastguard Worker                del self._readline  # restore FileInput._readline
276*cda5da8dSAndroid Build Coastguard Worker            except AttributeError:
277*cda5da8dSAndroid Build Coastguard Worker                pass
278*cda5da8dSAndroid Build Coastguard Worker            try:
279*cda5da8dSAndroid Build Coastguard Worker                if file and not self._isstdin:
280*cda5da8dSAndroid Build Coastguard Worker                    file.close()
281*cda5da8dSAndroid Build Coastguard Worker            finally:
282*cda5da8dSAndroid Build Coastguard Worker                backupfilename = self._backupfilename
283*cda5da8dSAndroid Build Coastguard Worker                self._backupfilename = None
284*cda5da8dSAndroid Build Coastguard Worker                if backupfilename and not self._backup:
285*cda5da8dSAndroid Build Coastguard Worker                    try: os.unlink(backupfilename)
286*cda5da8dSAndroid Build Coastguard Worker                    except OSError: pass
287*cda5da8dSAndroid Build Coastguard Worker
288*cda5da8dSAndroid Build Coastguard Worker                self._isstdin = False
289*cda5da8dSAndroid Build Coastguard Worker
290*cda5da8dSAndroid Build Coastguard Worker    def readline(self):
291*cda5da8dSAndroid Build Coastguard Worker        while True:
292*cda5da8dSAndroid Build Coastguard Worker            line = self._readline()
293*cda5da8dSAndroid Build Coastguard Worker            if line:
294*cda5da8dSAndroid Build Coastguard Worker                self._filelineno += 1
295*cda5da8dSAndroid Build Coastguard Worker                return line
296*cda5da8dSAndroid Build Coastguard Worker            if not self._file:
297*cda5da8dSAndroid Build Coastguard Worker                return line
298*cda5da8dSAndroid Build Coastguard Worker            self.nextfile()
299*cda5da8dSAndroid Build Coastguard Worker            # repeat with next file
300*cda5da8dSAndroid Build Coastguard Worker
301*cda5da8dSAndroid Build Coastguard Worker    def _readline(self):
302*cda5da8dSAndroid Build Coastguard Worker        if not self._files:
303*cda5da8dSAndroid Build Coastguard Worker            if 'b' in self._mode:
304*cda5da8dSAndroid Build Coastguard Worker                return b''
305*cda5da8dSAndroid Build Coastguard Worker            else:
306*cda5da8dSAndroid Build Coastguard Worker                return ''
307*cda5da8dSAndroid Build Coastguard Worker        self._filename = self._files[0]
308*cda5da8dSAndroid Build Coastguard Worker        self._files = self._files[1:]
309*cda5da8dSAndroid Build Coastguard Worker        self._startlineno = self.lineno()
310*cda5da8dSAndroid Build Coastguard Worker        self._filelineno = 0
311*cda5da8dSAndroid Build Coastguard Worker        self._file = None
312*cda5da8dSAndroid Build Coastguard Worker        self._isstdin = False
313*cda5da8dSAndroid Build Coastguard Worker        self._backupfilename = 0
314*cda5da8dSAndroid Build Coastguard Worker
315*cda5da8dSAndroid Build Coastguard Worker        # EncodingWarning is emitted in __init__() already
316*cda5da8dSAndroid Build Coastguard Worker        if "b" not in self._mode:
317*cda5da8dSAndroid Build Coastguard Worker            encoding = self._encoding or "locale"
318*cda5da8dSAndroid Build Coastguard Worker        else:
319*cda5da8dSAndroid Build Coastguard Worker            encoding = None
320*cda5da8dSAndroid Build Coastguard Worker
321*cda5da8dSAndroid Build Coastguard Worker        if self._filename == '-':
322*cda5da8dSAndroid Build Coastguard Worker            self._filename = '<stdin>'
323*cda5da8dSAndroid Build Coastguard Worker            if 'b' in self._mode:
324*cda5da8dSAndroid Build Coastguard Worker                self._file = getattr(sys.stdin, 'buffer', sys.stdin)
325*cda5da8dSAndroid Build Coastguard Worker            else:
326*cda5da8dSAndroid Build Coastguard Worker                self._file = sys.stdin
327*cda5da8dSAndroid Build Coastguard Worker            self._isstdin = True
328*cda5da8dSAndroid Build Coastguard Worker        else:
329*cda5da8dSAndroid Build Coastguard Worker            if self._inplace:
330*cda5da8dSAndroid Build Coastguard Worker                self._backupfilename = (
331*cda5da8dSAndroid Build Coastguard Worker                    os.fspath(self._filename) + (self._backup or ".bak"))
332*cda5da8dSAndroid Build Coastguard Worker                try:
333*cda5da8dSAndroid Build Coastguard Worker                    os.unlink(self._backupfilename)
334*cda5da8dSAndroid Build Coastguard Worker                except OSError:
335*cda5da8dSAndroid Build Coastguard Worker                    pass
336*cda5da8dSAndroid Build Coastguard Worker                # The next few lines may raise OSError
337*cda5da8dSAndroid Build Coastguard Worker                os.rename(self._filename, self._backupfilename)
338*cda5da8dSAndroid Build Coastguard Worker                self._file = open(self._backupfilename, self._mode,
339*cda5da8dSAndroid Build Coastguard Worker                                  encoding=encoding, errors=self._errors)
340*cda5da8dSAndroid Build Coastguard Worker                try:
341*cda5da8dSAndroid Build Coastguard Worker                    perm = os.fstat(self._file.fileno()).st_mode
342*cda5da8dSAndroid Build Coastguard Worker                except OSError:
343*cda5da8dSAndroid Build Coastguard Worker                    self._output = open(self._filename, self._write_mode,
344*cda5da8dSAndroid Build Coastguard Worker                                        encoding=encoding, errors=self._errors)
345*cda5da8dSAndroid Build Coastguard Worker                else:
346*cda5da8dSAndroid Build Coastguard Worker                    mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC
347*cda5da8dSAndroid Build Coastguard Worker                    if hasattr(os, 'O_BINARY'):
348*cda5da8dSAndroid Build Coastguard Worker                        mode |= os.O_BINARY
349*cda5da8dSAndroid Build Coastguard Worker
350*cda5da8dSAndroid Build Coastguard Worker                    fd = os.open(self._filename, mode, perm)
351*cda5da8dSAndroid Build Coastguard Worker                    self._output = os.fdopen(fd, self._write_mode,
352*cda5da8dSAndroid Build Coastguard Worker                                             encoding=encoding, errors=self._errors)
353*cda5da8dSAndroid Build Coastguard Worker                    try:
354*cda5da8dSAndroid Build Coastguard Worker                        os.chmod(self._filename, perm)
355*cda5da8dSAndroid Build Coastguard Worker                    except OSError:
356*cda5da8dSAndroid Build Coastguard Worker                        pass
357*cda5da8dSAndroid Build Coastguard Worker                self._savestdout = sys.stdout
358*cda5da8dSAndroid Build Coastguard Worker                sys.stdout = self._output
359*cda5da8dSAndroid Build Coastguard Worker            else:
360*cda5da8dSAndroid Build Coastguard Worker                # This may raise OSError
361*cda5da8dSAndroid Build Coastguard Worker                if self._openhook:
362*cda5da8dSAndroid Build Coastguard Worker                    # Custom hooks made previous to Python 3.10 didn't have
363*cda5da8dSAndroid Build Coastguard Worker                    # encoding argument
364*cda5da8dSAndroid Build Coastguard Worker                    if self._encoding is None:
365*cda5da8dSAndroid Build Coastguard Worker                        self._file = self._openhook(self._filename, self._mode)
366*cda5da8dSAndroid Build Coastguard Worker                    else:
367*cda5da8dSAndroid Build Coastguard Worker                        self._file = self._openhook(
368*cda5da8dSAndroid Build Coastguard Worker                            self._filename, self._mode, encoding=self._encoding, errors=self._errors)
369*cda5da8dSAndroid Build Coastguard Worker                else:
370*cda5da8dSAndroid Build Coastguard Worker                    self._file = open(self._filename, self._mode, encoding=encoding, errors=self._errors)
371*cda5da8dSAndroid Build Coastguard Worker        self._readline = self._file.readline  # hide FileInput._readline
372*cda5da8dSAndroid Build Coastguard Worker        return self._readline()
373*cda5da8dSAndroid Build Coastguard Worker
374*cda5da8dSAndroid Build Coastguard Worker    def filename(self):
375*cda5da8dSAndroid Build Coastguard Worker        return self._filename
376*cda5da8dSAndroid Build Coastguard Worker
377*cda5da8dSAndroid Build Coastguard Worker    def lineno(self):
378*cda5da8dSAndroid Build Coastguard Worker        return self._startlineno + self._filelineno
379*cda5da8dSAndroid Build Coastguard Worker
380*cda5da8dSAndroid Build Coastguard Worker    def filelineno(self):
381*cda5da8dSAndroid Build Coastguard Worker        return self._filelineno
382*cda5da8dSAndroid Build Coastguard Worker
383*cda5da8dSAndroid Build Coastguard Worker    def fileno(self):
384*cda5da8dSAndroid Build Coastguard Worker        if self._file:
385*cda5da8dSAndroid Build Coastguard Worker            try:
386*cda5da8dSAndroid Build Coastguard Worker                return self._file.fileno()
387*cda5da8dSAndroid Build Coastguard Worker            except ValueError:
388*cda5da8dSAndroid Build Coastguard Worker                return -1
389*cda5da8dSAndroid Build Coastguard Worker        else:
390*cda5da8dSAndroid Build Coastguard Worker            return -1
391*cda5da8dSAndroid Build Coastguard Worker
392*cda5da8dSAndroid Build Coastguard Worker    def isfirstline(self):
393*cda5da8dSAndroid Build Coastguard Worker        return self._filelineno == 1
394*cda5da8dSAndroid Build Coastguard Worker
395*cda5da8dSAndroid Build Coastguard Worker    def isstdin(self):
396*cda5da8dSAndroid Build Coastguard Worker        return self._isstdin
397*cda5da8dSAndroid Build Coastguard Worker
398*cda5da8dSAndroid Build Coastguard Worker    __class_getitem__ = classmethod(GenericAlias)
399*cda5da8dSAndroid Build Coastguard Worker
400*cda5da8dSAndroid Build Coastguard Worker
401*cda5da8dSAndroid Build Coastguard Workerdef hook_compressed(filename, mode, *, encoding=None, errors=None):
402*cda5da8dSAndroid Build Coastguard Worker    if encoding is None and "b" not in mode:  # EncodingWarning is emitted in FileInput() already.
403*cda5da8dSAndroid Build Coastguard Worker        encoding = "locale"
404*cda5da8dSAndroid Build Coastguard Worker    ext = os.path.splitext(filename)[1]
405*cda5da8dSAndroid Build Coastguard Worker    if ext == '.gz':
406*cda5da8dSAndroid Build Coastguard Worker        import gzip
407*cda5da8dSAndroid Build Coastguard Worker        stream = gzip.open(filename, mode)
408*cda5da8dSAndroid Build Coastguard Worker    elif ext == '.bz2':
409*cda5da8dSAndroid Build Coastguard Worker        import bz2
410*cda5da8dSAndroid Build Coastguard Worker        stream = bz2.BZ2File(filename, mode)
411*cda5da8dSAndroid Build Coastguard Worker    else:
412*cda5da8dSAndroid Build Coastguard Worker        return open(filename, mode, encoding=encoding, errors=errors)
413*cda5da8dSAndroid Build Coastguard Worker
414*cda5da8dSAndroid Build Coastguard Worker    # gzip and bz2 are binary mode by default.
415*cda5da8dSAndroid Build Coastguard Worker    if "b" not in mode:
416*cda5da8dSAndroid Build Coastguard Worker        stream = io.TextIOWrapper(stream, encoding=encoding, errors=errors)
417*cda5da8dSAndroid Build Coastguard Worker    return stream
418*cda5da8dSAndroid Build Coastguard Worker
419*cda5da8dSAndroid Build Coastguard Worker
420*cda5da8dSAndroid Build Coastguard Workerdef hook_encoded(encoding, errors=None):
421*cda5da8dSAndroid Build Coastguard Worker    def openhook(filename, mode):
422*cda5da8dSAndroid Build Coastguard Worker        return open(filename, mode, encoding=encoding, errors=errors)
423*cda5da8dSAndroid Build Coastguard Worker    return openhook
424*cda5da8dSAndroid Build Coastguard Worker
425*cda5da8dSAndroid Build Coastguard Worker
426*cda5da8dSAndroid Build Coastguard Workerdef _test():
427*cda5da8dSAndroid Build Coastguard Worker    import getopt
428*cda5da8dSAndroid Build Coastguard Worker    inplace = False
429*cda5da8dSAndroid Build Coastguard Worker    backup = False
430*cda5da8dSAndroid Build Coastguard Worker    opts, args = getopt.getopt(sys.argv[1:], "ib:")
431*cda5da8dSAndroid Build Coastguard Worker    for o, a in opts:
432*cda5da8dSAndroid Build Coastguard Worker        if o == '-i': inplace = True
433*cda5da8dSAndroid Build Coastguard Worker        if o == '-b': backup = a
434*cda5da8dSAndroid Build Coastguard Worker    for line in input(args, inplace=inplace, backup=backup):
435*cda5da8dSAndroid Build Coastguard Worker        if line[-1:] == '\n': line = line[:-1]
436*cda5da8dSAndroid Build Coastguard Worker        if line[-1:] == '\r': line = line[:-1]
437*cda5da8dSAndroid Build Coastguard Worker        print("%d: %s[%d]%s %s" % (lineno(), filename(), filelineno(),
438*cda5da8dSAndroid Build Coastguard Worker                                   isfirstline() and "*" or "", line))
439*cda5da8dSAndroid Build Coastguard Worker    print("%d: %s[%d]" % (lineno(), filename(), filelineno()))
440*cda5da8dSAndroid Build Coastguard Worker
441*cda5da8dSAndroid Build Coastguard Workerif __name__ == '__main__':
442*cda5da8dSAndroid Build Coastguard Worker    _test()
443