14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""Helper class to quickly write a loop over all standard input files.
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTypical use is:
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    import fileinput
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for line in fileinput.input():
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        process(line)
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmThis iterates over the lines of all files listed in sys.argv[1:],
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdefaulting to sys.stdin if the list is empty.  If a filename is '-' it
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmis also replaced by sys.stdin.  To specify an alternative list of
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfilenames, pass it as the argument to input().  A single file name is
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmalso allowed.
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFunctions filename(), lineno() return the filename and cumulative line
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmnumber of the line that has just been read; filelineno() returns its
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmline number in the current file; isfirstline() returns true iff the
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmline just read is the first line of its file; isstdin() returns true
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmiff the line was read from sys.stdin.  Function nextfile() closes the
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcurrent file so that the next iteration will read the first line from
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmthe next file (if any); lines not read from the file will not count
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtowards the cumulative line count; the filename is not changed until
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmafter the first line of the next file has been read.  Function close()
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcloses the sequence.
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmBefore any lines have been read, filename() returns None and both line
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmnumbers are zero; nextfile() has no effect.  After all lines have been
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmread, filename() and the line number functions return the values
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpertaining to the last line read; nextfile() has no effect.
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmAll files are opened in text mode by default, you can override this by
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsetting the mode parameter to input() or FileInput.__init__().
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmIf an I/O error occurs during opening or reading a file, the IOError
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmexception is raised.
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmIf sys.stdin is used more than once, the second and further use will
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmreturn no lines, except perhaps for interactive use, or if it has been
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmexplicitly reset (e.g. using sys.stdin.seek(0)).
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmEmpty files are opened and immediately closed; the only time their
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpresence in the list of filenames is noticeable at all is when the
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmlast file opened is empty.
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmIt is possible that the last line of a file doesn't end in a newline
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcharacter; otherwise lines are returned including the trailing
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmnewline.
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmClass FileInput is the implementation; its methods filename(),
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmlineno(), fileline(), isfirstline(), isstdin(), nextfile() and close()
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcorrespond to the functions in the module.  In addition it has a
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmreadline() method which returns the next input line, and a
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm__getitem__() method which implements the sequence behavior.  The
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsequence must be accessed in strictly sequential order; sequence
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmaccess and readline() cannot be mixed.
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmOptional in-place filtering: if the keyword argument inplace=1 is
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpassed to input() or to the FileInput constructor, the file is moved
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmto a backup file and standard output is directed to the input file.
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmThis makes it possible to write a filter that rewrites its input file
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmin place.  If the keyword argument backup=".<some extension>" is also
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmgiven, it specifies the extension for the backup file, and the backup
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfile remains around; by default, the extension is ".bak" and it is
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdeleted when the output file is closed.  In-place filtering is
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdisabled when standard input is read.  XXX The current implementation
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdoes not work for MS-DOS 8+3 filesystems.
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPerformance: this module is unfortunately one of the slower ways of
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprocessing large numbers of input lines.  Nevertheless, a significant
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmspeed-up has been obtained by using readlines(bufsize) instead of
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmreadline().  A new keyword argument, bufsize=N, is present on the
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylminput() function and the FileInput() class to override the default
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmbuffer size.
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmXXX Possible additions:
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm- optional getopt argument processing
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm- isatty()
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm- read(), read(size), even readlines()
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys, os
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm__all__ = ["input","close","nextfile","filename","lineno","filelineno",
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           "isfirstline","isstdin","FileInput"]
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_state = None
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDEFAULT_BUFSIZE = 8*1024
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef input(files=None, inplace=0, backup="", bufsize=0,
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          mode="r", openhook=None):
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """input([files[, inplace[, backup[, mode[, openhook]]]]])
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Create an instance of the FileInput class. The instance will be used
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    as global state for the functions of this module, and is also returned
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    to use during iteration. The parameters to this function will be passed
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    along to the constructor of the FileInput class.
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    global _state
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if _state and _state._file:
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise RuntimeError, "input() already active"
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    _state = FileInput(files, inplace, backup, bufsize, mode, openhook)
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _state
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef close():
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Close the sequence."""
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    global _state
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    state = _state
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    _state = None
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if state:
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        state.close()
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef nextfile():
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Close the current file so that the next iteration will read the first
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    line from the next file (if any); lines not read from the file will
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    not count towards the cumulative line count. The filename is not
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    changed until after the first line of the next file has been read.
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Before the first line has been read, this function has no effect;
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    it cannot be used to skip the first file. After the last line of the
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    last file has been read, this function has no effect.
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not _state:
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise RuntimeError, "no active input()"
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _state.nextfile()
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef filename():
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Return the name of the file currently being read.
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Before the first line has been read, returns None.
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not _state:
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise RuntimeError, "no active input()"
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _state.filename()
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef lineno():
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Return the cumulative line number of the line that has just been read.
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Before the first line has been read, returns 0. After the last line
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    of the last file has been read, returns the line number of that line.
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not _state:
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise RuntimeError, "no active input()"
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _state.lineno()
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef filelineno():
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Return the line number in the current file. Before the first line
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    has been read, returns 0. After the last line of the last file has
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    been read, returns the line number of that line within the file.
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not _state:
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise RuntimeError, "no active input()"
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _state.filelineno()
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef fileno():
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Return the file number of the current file. When no file is currently
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    opened, returns -1.
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not _state:
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise RuntimeError, "no active input()"
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _state.fileno()
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef isfirstline():
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Returns true the line just read is the first line of its file,
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    otherwise returns false.
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not _state:
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise RuntimeError, "no active input()"
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _state.isfirstline()
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef isstdin():
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Returns true if the last line was read from sys.stdin,
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    otherwise returns false.
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not _state:
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise RuntimeError, "no active input()"
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _state.isstdin()
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass FileInput:
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """class FileInput([files[, inplace[, backup[, mode[, openhook]]]]])
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Class FileInput is the implementation of the module; its methods
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    filename(), lineno(), fileline(), isfirstline(), isstdin(), fileno(),
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    nextfile() and close() correspond to the functions of the same name
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    in the module.
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    In addition it has a readline() method which returns the next
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    input line, and a __getitem__() method which implements the
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sequence behavior. The sequence must be accessed in strictly
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sequential order; random access and readline() cannot be mixed.
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __init__(self, files=None, inplace=0, backup="", bufsize=0,
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                 mode="r", openhook=None):
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isinstance(files, basestring):
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            files = (files,)
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if files is None:
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                files = sys.argv[1:]
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not files:
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                files = ('-',)
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else:
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                files = tuple(files)
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._files = files
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._inplace = inplace
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._backup = backup
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._bufsize = bufsize or DEFAULT_BUFSIZE
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._savestdout = None
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._output = None
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._filename = None
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._lineno = 0
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._filelineno = 0
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._file = None
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._isstdin = False
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._backupfilename = None
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._buffer = []
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._bufindex = 0
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # restrict mode argument to reading modes
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if mode not in ('r', 'rU', 'U', 'rb'):
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise ValueError("FileInput opening mode must be one of "
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             "'r', 'rU', 'U' and 'rb'")
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._mode = mode
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if inplace and openhook:
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise ValueError("FileInput cannot use an opening hook in inplace mode")
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        elif openhook and not hasattr(openhook, '__call__'):
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise ValueError("FileInput openhook must be callable")
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._openhook = openhook
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __del__(self):
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.close()
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def close(self):
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.nextfile()
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._files = ()
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __iter__(self):
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def next(self):
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            line = self._buffer[self._bufindex]
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except IndexError:
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._bufindex += 1
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._lineno += 1
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._filelineno += 1
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return line
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        line = self.readline()
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not line:
2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise StopIteration
2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return line
2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __getitem__(self, i):
2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if i != self._lineno:
2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise RuntimeError, "accessing lines out of order"
2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return self.next()
2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except StopIteration:
2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise IndexError, "end of input reached"
2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def nextfile(self):
2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        savestdout = self._savestdout
2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._savestdout = 0
2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if savestdout:
2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sys.stdout = savestdout
2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        output = self._output
2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._output = 0
2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if output:
2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            output.close()
2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        file = self._file
2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._file = 0
2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if file and not self._isstdin:
2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            file.close()
2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        backupfilename = self._backupfilename
2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._backupfilename = 0
2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if backupfilename and not self._backup:
2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try: os.unlink(backupfilename)
2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except OSError: pass
2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._isstdin = False
2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._buffer = []
2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._bufindex = 0
2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def readline(self):
2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            line = self._buffer[self._bufindex]
2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except IndexError:
2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._bufindex += 1
2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._lineno += 1
3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._filelineno += 1
3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return line
3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not self._file:
3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not self._files:
3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return ""
3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._filename = self._files[0]
3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._files = self._files[1:]
3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._filelineno = 0
3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._file = None
3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._isstdin = False
3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self._backupfilename = 0
3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if self._filename == '-':
3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self._filename = '<stdin>'
3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self._file = sys.stdin
3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self._isstdin = True
3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else:
3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if self._inplace:
3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self._backupfilename = (
3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        self._filename + (self._backup or os.extsep+"bak"))
3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    try: os.unlink(self._backupfilename)
3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    except os.error: pass
3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    # The next few lines may raise IOError
3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    os.rename(self._filename, self._backupfilename)
3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self._file = open(self._backupfilename, self._mode)
3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    try:
3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        perm = os.fstat(self._file.fileno()).st_mode
3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    except OSError:
3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        self._output = open(self._filename, "w")
3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    else:
3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        fd = os.open(self._filename,
3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     os.O_CREAT | os.O_WRONLY | os.O_TRUNC,
3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     perm)
3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        self._output = os.fdopen(fd, "w")
3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        try:
3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            if hasattr(os, 'chmod'):
3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                os.chmod(self._filename, perm)
3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        except OSError:
3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            pass
3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self._savestdout = sys.stdout
3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    sys.stdout = self._output
3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                else:
3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    # This may raise IOError
3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    if self._openhook:
3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        self._file = self._openhook(self._filename, self._mode)
3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    else:
3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        self._file = open(self._filename, self._mode)
3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._buffer = self._file.readlines(self._bufsize)
3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._bufindex = 0
3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not self._buffer:
3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.nextfile()
3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Recursive call
3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self.readline()
3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def filename(self):
3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self._filename
3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def lineno(self):
3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self._lineno
3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def filelineno(self):
3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self._filelineno
3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def fileno(self):
3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if self._file:
3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return self._file.fileno()
3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except ValueError:
3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return -1
3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1
3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def isfirstline(self):
3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self._filelineno == 1
3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def isstdin(self):
3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self._isstdin
3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef hook_compressed(filename, mode):
3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ext = os.path.splitext(filename)[1]
3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if ext == '.gz':
3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import gzip
3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return gzip.open(filename, mode)
3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    elif ext == '.bz2':
3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import bz2
3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return bz2.BZ2File(filename, mode)
3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else:
3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return open(filename, mode)
3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef hook_encoded(encoding):
3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    import codecs
3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def openhook(filename, mode):
3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return codecs.open(filename, mode, encoding)
3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return openhook
3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef _test():
3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    import getopt
3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    inplace = 0
4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    backup = 0
4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    opts, args = getopt.getopt(sys.argv[1:], "ib:")
4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for o, a in opts:
4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if o == '-i': inplace = 1
4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if o == '-b': backup = a
4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for line in input(args, inplace=inplace, backup=backup):
4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if line[-1:] == '\n': line = line[:-1]
4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if line[-1:] == '\r': line = line[:-1]
4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        print "%d: %s[%d]%s %s" % (lineno(), filename(), filelineno(),
4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                   isfirstline() and "*" or "", line)
4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    print "%d: %s[%d]" % (lineno(), filename(), filelineno())
4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == '__main__':
4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    _test()
414