+++ /dev/null
-"""Helper class to quickly write a loop over all standard input files.\r
-\r
-Typical use is:\r
-\r
- import fileinput\r
- for line in fileinput.input():\r
- process(line)\r
-\r
-This iterates over the lines of all files listed in sys.argv[1:],\r
-defaulting to sys.stdin if the list is empty. If a filename is '-' it\r
-is also replaced by sys.stdin. To specify an alternative list of\r
-filenames, pass it as the argument to input(). A single file name is\r
-also allowed.\r
-\r
-Functions filename(), lineno() return the filename and cumulative line\r
-number of the line that has just been read; filelineno() returns its\r
-line number in the current file; isfirstline() returns true iff the\r
-line just read is the first line of its file; isstdin() returns true\r
-iff the line was read from sys.stdin. Function nextfile() closes the\r
-current file so that the next iteration will read the first line from\r
-the next file (if any); lines not read from the file will not count\r
-towards the cumulative line count; the filename is not changed until\r
-after the first line of the next file has been read. Function close()\r
-closes the sequence.\r
-\r
-Before any lines have been read, filename() returns None and both line\r
-numbers are zero; nextfile() has no effect. After all lines have been\r
-read, filename() and the line number functions return the values\r
-pertaining to the last line read; nextfile() has no effect.\r
-\r
-All files are opened in text mode by default, you can override this by\r
-setting the mode parameter to input() or FileInput.__init__().\r
-If an I/O error occurs during opening or reading a file, the IOError\r
-exception is raised.\r
-\r
-If sys.stdin is used more than once, the second and further use will\r
-return no lines, except perhaps for interactive use, or if it has been\r
-explicitly reset (e.g. using sys.stdin.seek(0)).\r
-\r
-Empty files are opened and immediately closed; the only time their\r
-presence in the list of filenames is noticeable at all is when the\r
-last file opened is empty.\r
-\r
-It is possible that the last line of a file doesn't end in a newline\r
-character; otherwise lines are returned including the trailing\r
-newline.\r
-\r
-Class FileInput is the implementation; its methods filename(),\r
-lineno(), fileline(), isfirstline(), isstdin(), nextfile() and close()\r
-correspond to the functions in the module. In addition it has a\r
-readline() method which returns the next input line, and a\r
-__getitem__() method which implements the sequence behavior. The\r
-sequence must be accessed in strictly sequential order; sequence\r
-access and readline() cannot be mixed.\r
-\r
-Optional in-place filtering: if the keyword argument inplace=1 is\r
-passed to input() or to the FileInput constructor, the file is moved\r
-to a backup file and standard output is directed to the input file.\r
-This makes it possible to write a filter that rewrites its input file\r
-in place. If the keyword argument backup=".<some extension>" is also\r
-given, it specifies the extension for the backup file, and the backup\r
-file remains around; by default, the extension is ".bak" and it is\r
-deleted when the output file is closed. In-place filtering is\r
-disabled when standard input is read. XXX The current implementation\r
-does not work for MS-DOS 8+3 filesystems.\r
-\r
-Performance: this module is unfortunately one of the slower ways of\r
-processing large numbers of input lines. Nevertheless, a significant\r
-speed-up has been obtained by using readlines(bufsize) instead of\r
-readline(). A new keyword argument, bufsize=N, is present on the\r
-input() function and the FileInput() class to override the default\r
-buffer size.\r
-\r
-XXX Possible additions:\r
-\r
-- optional getopt argument processing\r
-- isatty()\r
-- read(), read(size), even readlines()\r
-\r
-"""\r
-\r
-import sys, os\r
-\r
-__all__ = ["input","close","nextfile","filename","lineno","filelineno",\r
- "isfirstline","isstdin","FileInput"]\r
-\r
-_state = None\r
-\r
-DEFAULT_BUFSIZE = 8*1024\r
-\r
-def input(files=None, inplace=0, backup="", bufsize=0,\r
- mode="r", openhook=None):\r
- """input([files[, inplace[, backup[, mode[, openhook]]]]])\r
-\r
- Create an instance of the FileInput class. The instance will be used\r
- as global state for the functions of this module, and is also returned\r
- to use during iteration. The parameters to this function will be passed\r
- along to the constructor of the FileInput class.\r
- """\r
- global _state\r
- if _state and _state._file:\r
- raise RuntimeError, "input() already active"\r
- _state = FileInput(files, inplace, backup, bufsize, mode, openhook)\r
- return _state\r
-\r
-def close():\r
- """Close the sequence."""\r
- global _state\r
- state = _state\r
- _state = None\r
- if state:\r
- state.close()\r
-\r
-def nextfile():\r
- """\r
- Close the current file so that the next iteration will read the first\r
- line from the next file (if any); lines not read from the file will\r
- not count towards the cumulative line count. The filename is not\r
- changed until after the first line of the next file has been read.\r
- Before the first line has been read, this function has no effect;\r
- it cannot be used to skip the first file. After the last line of the\r
- last file has been read, this function has no effect.\r
- """\r
- if not _state:\r
- raise RuntimeError, "no active input()"\r
- return _state.nextfile()\r
-\r
-def filename():\r
- """\r
- Return the name of the file currently being read.\r
- Before the first line has been read, returns None.\r
- """\r
- if not _state:\r
- raise RuntimeError, "no active input()"\r
- return _state.filename()\r
-\r
-def lineno():\r
- """\r
- Return the cumulative line number of the line that has just been read.\r
- Before the first line has been read, returns 0. After the last line\r
- of the last file has been read, returns the line number of that line.\r
- """\r
- if not _state:\r
- raise RuntimeError, "no active input()"\r
- return _state.lineno()\r
-\r
-def filelineno():\r
- """\r
- Return the line number in the current file. Before the first line\r
- has been read, returns 0. After the last line of the last file has\r
- been read, returns the line number of that line within the file.\r
- """\r
- if not _state:\r
- raise RuntimeError, "no active input()"\r
- return _state.filelineno()\r
-\r
-def fileno():\r
- """\r
- Return the file number of the current file. When no file is currently\r
- opened, returns -1.\r
- """\r
- if not _state:\r
- raise RuntimeError, "no active input()"\r
- return _state.fileno()\r
-\r
-def isfirstline():\r
- """\r
- Returns true the line just read is the first line of its file,\r
- otherwise returns false.\r
- """\r
- if not _state:\r
- raise RuntimeError, "no active input()"\r
- return _state.isfirstline()\r
-\r
-def isstdin():\r
- """\r
- Returns true if the last line was read from sys.stdin,\r
- otherwise returns false.\r
- """\r
- if not _state:\r
- raise RuntimeError, "no active input()"\r
- return _state.isstdin()\r
-\r
-class FileInput:\r
- """class FileInput([files[, inplace[, backup[, mode[, openhook]]]]])\r
-\r
- Class FileInput is the implementation of the module; its methods\r
- filename(), lineno(), fileline(), isfirstline(), isstdin(), fileno(),\r
- nextfile() and close() correspond to the functions of the same name\r
- in the module.\r
- In addition it has a readline() method which returns the next\r
- input line, and a __getitem__() method which implements the\r
- sequence behavior. The sequence must be accessed in strictly\r
- sequential order; random access and readline() cannot be mixed.\r
- """\r
-\r
- def __init__(self, files=None, inplace=0, backup="", bufsize=0,\r
- mode="r", openhook=None):\r
- if isinstance(files, basestring):\r
- files = (files,)\r
- else:\r
- if files is None:\r
- files = sys.argv[1:]\r
- if not files:\r
- files = ('-',)\r
- else:\r
- files = tuple(files)\r
- self._files = files\r
- self._inplace = inplace\r
- self._backup = backup\r
- self._bufsize = bufsize or DEFAULT_BUFSIZE\r
- self._savestdout = None\r
- self._output = None\r
- self._filename = None\r
- self._lineno = 0\r
- self._filelineno = 0\r
- self._file = None\r
- self._isstdin = False\r
- self._backupfilename = None\r
- self._buffer = []\r
- self._bufindex = 0\r
- # restrict mode argument to reading modes\r
- if mode not in ('r', 'rU', 'U', 'rb'):\r
- raise ValueError("FileInput opening mode must be one of "\r
- "'r', 'rU', 'U' and 'rb'")\r
- self._mode = mode\r
- if inplace and openhook:\r
- raise ValueError("FileInput cannot use an opening hook in inplace mode")\r
- elif openhook and not hasattr(openhook, '__call__'):\r
- raise ValueError("FileInput openhook must be callable")\r
- self._openhook = openhook\r
-\r
- def __del__(self):\r
- self.close()\r
-\r
- def close(self):\r
- self.nextfile()\r
- self._files = ()\r
-\r
- def __iter__(self):\r
- return self\r
-\r
- def next(self):\r
- try:\r
- line = self._buffer[self._bufindex]\r
- except IndexError:\r
- pass\r
- else:\r
- self._bufindex += 1\r
- self._lineno += 1\r
- self._filelineno += 1\r
- return line\r
- line = self.readline()\r
- if not line:\r
- raise StopIteration\r
- return line\r
-\r
- def __getitem__(self, i):\r
- if i != self._lineno:\r
- raise RuntimeError, "accessing lines out of order"\r
- try:\r
- return self.next()\r
- except StopIteration:\r
- raise IndexError, "end of input reached"\r
-\r
- def nextfile(self):\r
- savestdout = self._savestdout\r
- self._savestdout = 0\r
- if savestdout:\r
- sys.stdout = savestdout\r
-\r
- output = self._output\r
- self._output = 0\r
- if output:\r
- output.close()\r
-\r
- file = self._file\r
- self._file = 0\r
- if file and not self._isstdin:\r
- file.close()\r
-\r
- backupfilename = self._backupfilename\r
- self._backupfilename = 0\r
- if backupfilename and not self._backup:\r
- try: os.unlink(backupfilename)\r
- except OSError: pass\r
-\r
- self._isstdin = False\r
- self._buffer = []\r
- self._bufindex = 0\r
-\r
- def readline(self):\r
- try:\r
- line = self._buffer[self._bufindex]\r
- except IndexError:\r
- pass\r
- else:\r
- self._bufindex += 1\r
- self._lineno += 1\r
- self._filelineno += 1\r
- return line\r
- if not self._file:\r
- if not self._files:\r
- return ""\r
- self._filename = self._files[0]\r
- self._files = self._files[1:]\r
- self._filelineno = 0\r
- self._file = None\r
- self._isstdin = False\r
- self._backupfilename = 0\r
- if self._filename == '-':\r
- self._filename = '<stdin>'\r
- self._file = sys.stdin\r
- self._isstdin = True\r
- else:\r
- if self._inplace:\r
- self._backupfilename = (\r
- self._filename + (self._backup or os.extsep+"bak"))\r
- try: os.unlink(self._backupfilename)\r
- except os.error: pass\r
- # The next few lines may raise IOError\r
- os.rename(self._filename, self._backupfilename)\r
- self._file = open(self._backupfilename, self._mode)\r
- try:\r
- perm = os.fstat(self._file.fileno()).st_mode\r
- except OSError:\r
- self._output = open(self._filename, "w")\r
- else:\r
- fd = os.open(self._filename,\r
- os.O_CREAT | os.O_WRONLY | os.O_TRUNC,\r
- perm)\r
- self._output = os.fdopen(fd, "w")\r
- try:\r
- if hasattr(os, 'chmod'):\r
- os.chmod(self._filename, perm)\r
- except OSError:\r
- pass\r
- self._savestdout = sys.stdout\r
- sys.stdout = self._output\r
- else:\r
- # This may raise IOError\r
- if self._openhook:\r
- self._file = self._openhook(self._filename, self._mode)\r
- else:\r
- self._file = open(self._filename, self._mode)\r
- self._buffer = self._file.readlines(self._bufsize)\r
- self._bufindex = 0\r
- if not self._buffer:\r
- self.nextfile()\r
- # Recursive call\r
- return self.readline()\r
-\r
- def filename(self):\r
- return self._filename\r
-\r
- def lineno(self):\r
- return self._lineno\r
-\r
- def filelineno(self):\r
- return self._filelineno\r
-\r
- def fileno(self):\r
- if self._file:\r
- try:\r
- return self._file.fileno()\r
- except ValueError:\r
- return -1\r
- else:\r
- return -1\r
-\r
- def isfirstline(self):\r
- return self._filelineno == 1\r
-\r
- def isstdin(self):\r
- return self._isstdin\r
-\r
-\r
-def hook_compressed(filename, mode):\r
- ext = os.path.splitext(filename)[1]\r
- if ext == '.gz':\r
- import gzip\r
- return gzip.open(filename, mode)\r
- elif ext == '.bz2':\r
- import bz2\r
- return bz2.BZ2File(filename, mode)\r
- else:\r
- return open(filename, mode)\r
-\r
-\r
-def hook_encoded(encoding):\r
- import codecs\r
- def openhook(filename, mode):\r
- return codecs.open(filename, mode, encoding)\r
- return openhook\r
-\r
-\r
-def _test():\r
- import getopt\r
- inplace = 0\r
- backup = 0\r
- opts, args = getopt.getopt(sys.argv[1:], "ib:")\r
- for o, a in opts:\r
- if o == '-i': inplace = 1\r
- if o == '-b': backup = a\r
- for line in input(args, inplace=inplace, backup=backup):\r
- if line[-1:] == '\n': line = line[:-1]\r
- if line[-1:] == '\r': line = line[:-1]\r
- print "%d: %s[%d]%s %s" % (lineno(), filename(), filelineno(),\r
- isfirstline() and "*" or "", line)\r
- print "%d: %s[%d]" % (lineno(), filename(), filelineno())\r
-\r
-if __name__ == '__main__':\r
- _test()\r