13257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel"""Helper class to quickly write a loop over all standard input files. 23257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 33257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielTypical use is: 43257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 53257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel import fileinput 63257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for line in fileinput.input(): 73257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel process(line) 83257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 93257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielThis iterates over the lines of all files listed in sys.argv[1:], 103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldefaulting to sys.stdin if the list is empty. If a filename is '-' it 113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielis also replaced by sys.stdin. To specify an alternative list of 123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielfilenames, pass it as the argument to input(). A single file name is 133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielalso allowed. 143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielFunctions filename(), lineno() return the filename and cumulative line 163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielnumber of the line that has just been read; filelineno() returns its 173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielline number in the current file; isfirstline() returns true iff the 183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielline just read is the first line of its file; isstdin() returns true 193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieliff the line was read from sys.stdin. Function nextfile() closes the 203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielcurrent file so that the next iteration will read the first line from 213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielthe next file (if any); lines not read from the file will not count 223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieltowards the cumulative line count; the filename is not changed until 233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielafter the first line of the next file has been read. Function close() 243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielcloses the sequence. 253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielBefore any lines have been read, filename() returns None and both line 273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielnumbers are zero; nextfile() has no effect. After all lines have been 283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielread, filename() and the line number functions return the values 293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielpertaining to the last line read; nextfile() has no effect. 303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielAll files are opened in text mode by default, you can override this by 323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielsetting the mode parameter to input() or FileInput.__init__(). 333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielIf an I/O error occurs during opening or reading a file, the IOError 343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielexception is raised. 353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielIf sys.stdin is used more than once, the second and further use will 373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielreturn no lines, except perhaps for interactive use, or if it has been 383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielexplicitly reset (e.g. using sys.stdin.seek(0)). 393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielEmpty files are opened and immediately closed; the only time their 413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielpresence in the list of filenames is noticeable at all is when the 423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniellast file opened is empty. 433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielIt is possible that the last line of a file doesn't end in a newline 453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielcharacter; otherwise lines are returned including the trailing 463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielnewline. 473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielClass FileInput is the implementation; its methods filename(), 493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniellineno(), fileline(), isfirstline(), isstdin(), nextfile() and close() 503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielcorrespond to the functions in the module. In addition it has a 513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielreadline() method which returns the next input line, and a 523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel__getitem__() method which implements the sequence behavior. The 533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielsequence must be accessed in strictly sequential order; sequence 543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielaccess and readline() cannot be mixed. 553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielOptional in-place filtering: if the keyword argument inplace=1 is 573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielpassed to input() or to the FileInput constructor, the file is moved 583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielto a backup file and standard output is directed to the input file. 593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielThis makes it possible to write a filter that rewrites its input file 603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielin place. If the keyword argument backup=".<some extension>" is also 613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielgiven, it specifies the extension for the backup file, and the backup 623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielfile remains around; by default, the extension is ".bak" and it is 633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldeleted when the output file is closed. In-place filtering is 643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldisabled when standard input is read. XXX The current implementation 653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldoes not work for MS-DOS 8+3 filesystems. 663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielPerformance: this module is unfortunately one of the slower ways of 683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielprocessing large numbers of input lines. Nevertheless, a significant 693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielspeed-up has been obtained by using readlines(bufsize) instead of 703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielreadline(). A new keyword argument, bufsize=N, is present on the 713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielinput() function and the FileInput() class to override the default 723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielbuffer size. 733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielXXX Possible additions: 753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel- optional getopt argument processing 773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel- isatty() 783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel- read(), read(size), even readlines() 793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel""" 813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport sys, os 833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel__all__ = ["input","close","nextfile","filename","lineno","filelineno", 853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel "isfirstline","isstdin","FileInput"] 863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel_state = None 883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielDEFAULT_BUFSIZE = 8*1024 903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef input(files=None, inplace=0, backup="", bufsize=0, 923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel mode="r", openhook=None): 933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """Return an instance of the FileInput class, which can be iterated. 943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel The parameters are passed to the constructor of the FileInput class. 963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel The returned instance, in addition to being an iterator, 973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel keeps global state for the functions of this module,. 983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel global _state 1003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if _state and _state._file: 1013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise RuntimeError, "input() already active" 1023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel _state = FileInput(files, inplace, backup, bufsize, mode, openhook) 1033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return _state 1043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef close(): 1063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """Close the sequence.""" 1073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel global _state 1083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel state = _state 1093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel _state = None 1103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if state: 1113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel state.close() 1123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef nextfile(): 1143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Close the current file so that the next iteration will read the first 1163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel line from the next file (if any); lines not read from the file will 1173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel not count towards the cumulative line count. The filename is not 1183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel changed until after the first line of the next file has been read. 1193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Before the first line has been read, this function has no effect; 1203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel it cannot be used to skip the first file. After the last line of the 1213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel last file has been read, this function has no effect. 1223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not _state: 1243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise RuntimeError, "no active input()" 1253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return _state.nextfile() 1263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef filename(): 1283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Return the name of the file currently being read. 1303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Before the first line has been read, returns None. 1313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not _state: 1333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise RuntimeError, "no active input()" 1343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return _state.filename() 1353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef lineno(): 1373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Return the cumulative line number of the line that has just been read. 1393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Before the first line has been read, returns 0. After the last line 1403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel of the last file has been read, returns the line number of that line. 1413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not _state: 1433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise RuntimeError, "no active input()" 1443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return _state.lineno() 1453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef filelineno(): 1473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Return the line number in the current file. Before the first line 1493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel has been read, returns 0. After the last line of the last file has 1503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel been read, returns the line number of that line within the file. 1513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not _state: 1533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise RuntimeError, "no active input()" 1543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return _state.filelineno() 1553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef fileno(): 1573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Return the file number of the current file. When no file is currently 1593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel opened, returns -1. 1603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not _state: 1623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise RuntimeError, "no active input()" 1633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return _state.fileno() 1643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef isfirstline(): 1663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Returns true the line just read is the first line of its file, 1683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel otherwise returns false. 1693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not _state: 1713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise RuntimeError, "no active input()" 1723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return _state.isfirstline() 1733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef isstdin(): 1753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Returns true if the last line was read from sys.stdin, 1773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel otherwise returns false. 1783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not _state: 1803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise RuntimeError, "no active input()" 1813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return _state.isstdin() 1823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass FileInput: 1843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """FileInput([files[, inplace[, backup[, bufsize[, mode[, openhook]]]]]]) 1853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Class FileInput is the implementation of the module; its methods 1873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel filename(), lineno(), fileline(), isfirstline(), isstdin(), fileno(), 1883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel nextfile() and close() correspond to the functions of the same name 1893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel in the module. 1903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel In addition it has a readline() method which returns the next 1913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel input line, and a __getitem__() method which implements the 1923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel sequence behavior. The sequence must be accessed in strictly 1933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel sequential order; random access and readline() cannot be mixed. 1943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __init__(self, files=None, inplace=0, backup="", bufsize=0, 1973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel mode="r", openhook=None): 1983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if isinstance(files, basestring): 1993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel files = (files,) 2003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 2013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if files is None: 2023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel files = sys.argv[1:] 2033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not files: 2043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel files = ('-',) 2053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 2063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel files = tuple(files) 2073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._files = files 2083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._inplace = inplace 2093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._backup = backup 2103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._bufsize = bufsize or DEFAULT_BUFSIZE 2113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._savestdout = None 2123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._output = None 2133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._filename = None 2143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._lineno = 0 2153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._filelineno = 0 2163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._file = None 2173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._isstdin = False 2183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._backupfilename = None 2193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._buffer = [] 2203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._bufindex = 0 2213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # restrict mode argument to reading modes 2223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if mode not in ('r', 'rU', 'U', 'rb'): 2233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise ValueError("FileInput opening mode must be one of " 2243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel "'r', 'rU', 'U' and 'rb'") 2253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._mode = mode 2263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if inplace and openhook: 2273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise ValueError("FileInput cannot use an opening hook in inplace mode") 2283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel elif openhook and not hasattr(openhook, '__call__'): 2293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise ValueError("FileInput openhook must be callable") 2303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._openhook = openhook 2313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __del__(self): 2333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.close() 2343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def close(self): 2363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: 2373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.nextfile() 2383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel finally: 2393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._files = () 2403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __iter__(self): 2423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return self 2433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def next(self): 2453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: 2463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel line = self._buffer[self._bufindex] 2473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel except IndexError: 2483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel pass 2493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 2503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._bufindex += 1 2513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._lineno += 1 2523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._filelineno += 1 2533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return line 2543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel line = self.readline() 2553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not line: 2563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise StopIteration 2573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return line 2583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __getitem__(self, i): 2603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if i != self._lineno: 2613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise RuntimeError, "accessing lines out of order" 2623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: 2633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return self.next() 2643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel except StopIteration: 2653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise IndexError, "end of input reached" 2663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def nextfile(self): 2683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel savestdout = self._savestdout 2693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._savestdout = 0 2703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if savestdout: 2713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel sys.stdout = savestdout 2723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel output = self._output 2743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._output = 0 2753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: 2763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if output: 2773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel output.close() 2783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel finally: 2793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel file = self._file 2803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._file = 0 2813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: 2823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if file and not self._isstdin: 2833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel file.close() 2843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel finally: 2853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel backupfilename = self._backupfilename 2863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._backupfilename = 0 2873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if backupfilename and not self._backup: 2883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: os.unlink(backupfilename) 2893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel except OSError: pass 2903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._isstdin = False 2923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._buffer = [] 2933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._bufindex = 0 2943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def readline(self): 2963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: 2973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel line = self._buffer[self._bufindex] 2983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel except IndexError: 2993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel pass 3003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._bufindex += 1 3023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._lineno += 1 3033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._filelineno += 1 3043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return line 3053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not self._file: 3063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not self._files: 3073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return "" 3083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._filename = self._files[0] 3093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._files = self._files[1:] 3103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._filelineno = 0 3113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._file = None 3123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._isstdin = False 3133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._backupfilename = 0 3143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self._filename == '-': 3153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._filename = '<stdin>' 3163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._file = sys.stdin 3173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._isstdin = True 3183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self._inplace: 3203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._backupfilename = ( 3213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._filename + (self._backup or os.extsep+"bak")) 3223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: os.unlink(self._backupfilename) 3233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel except os.error: pass 3243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # The next few lines may raise IOError 3253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel os.rename(self._filename, self._backupfilename) 3263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._file = open(self._backupfilename, self._mode) 3273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: 3283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel perm = os.fstat(self._file.fileno()).st_mode 3293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel except OSError: 3303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._output = open(self._filename, "w") 3313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel fd = os.open(self._filename, 3333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel os.O_CREAT | os.O_WRONLY | os.O_TRUNC, 3343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel perm) 3353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._output = os.fdopen(fd, "w") 3363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: 3373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if hasattr(os, 'chmod'): 3383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel os.chmod(self._filename, perm) 3393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel except OSError: 3403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel pass 3413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._savestdout = sys.stdout 3423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel sys.stdout = self._output 3433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # This may raise IOError 3453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self._openhook: 3463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._file = self._openhook(self._filename, self._mode) 3473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._file = open(self._filename, self._mode) 3493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._buffer = self._file.readlines(self._bufsize) 3503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self._bufindex = 0 3513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not self._buffer: 3523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.nextfile() 3533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # Recursive call 3543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return self.readline() 3553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def filename(self): 3573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return self._filename 3583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def lineno(self): 3603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return self._lineno 3613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def filelineno(self): 3633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return self._filelineno 3643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def fileno(self): 3663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self._file: 3673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: 3683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return self._file.fileno() 3693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel except ValueError: 3703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return -1 3713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return -1 3733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def isfirstline(self): 3753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return self._filelineno == 1 3763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def isstdin(self): 3783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return self._isstdin 3793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef hook_compressed(filename, mode): 3823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel ext = os.path.splitext(filename)[1] 3833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if ext == '.gz': 3843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel import gzip 3853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return gzip.open(filename, mode) 3863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel elif ext == '.bz2': 3873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel import bz2 3883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return bz2.BZ2File(filename, mode) 3893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return open(filename, mode) 3913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef hook_encoded(encoding): 3943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel import io 3953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def openhook(filename, mode): 3963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel mode = mode.replace('U', '').replace('b', '') or 'r' 3973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return io.open(filename, mode, encoding=encoding, newline='') 3983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return openhook 3993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 4003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 4013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _test(): 4023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel import getopt 4033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel inplace = 0 4043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel backup = 0 4053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel opts, args = getopt.getopt(sys.argv[1:], "ib:") 4063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for o, a in opts: 4073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if o == '-i': inplace = 1 4083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if o == '-b': backup = a 4093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for line in input(args, inplace=inplace, backup=backup): 4103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if line[-1:] == '\n': line = line[:-1] 4113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if line[-1:] == '\r': line = line[:-1] 4123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "%d: %s[%d]%s %s" % (lineno(), filename(), filelineno(), 4133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel isfirstline() and "*" or "", line) 4143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "%d: %s[%d]" % (lineno(), filename(), filelineno()) 4153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 4163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielif __name__ == '__main__': 4173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel _test() 418