--- /dev/null
+"""
+Handling of arguments: options, arguments, file(s) content iterator
+
+For small scripts that:
+- read some command line options
+- read some command line positional arguments
+- iterate over all lines of some files given on the command line, or stdin if none given
+- give usage message if positional arguments are missing
+- give usage message if input files are missing and stdin is not redirected
+"""
+
+__author__ = 'Peter Kleiweg'
+__version__ = '0.2'
+__date__ = '2004/08/28'
+
+import os, sys, getopt
+
+class Args:
+ """
+ Perform common tasks on command line arguments
+
+ Instance data:
+ progname (string) -- name of program
+ opt (dictionary) -- options with values
+ infile (string) -- name of current file being processed
+ lineno (int) -- line number of last line read in current file
+ linesum (int) -- total of lines read
+ """
+
+ def __init__(self, usage='Usage: %(progname)s [opt...] [file...]'):
+ "init, usage string: embed program name as %(progname)s"
+ self.progname = os.path.basename(sys.argv[0])
+ self.opt = {}
+ self.infile = None
+ self.lineno = 0
+ self.linesum = 0
+ self._argv = sys.argv[1:]
+ self._usage = usage
+
+ def __iter__(self):
+ "iterator: set-up"
+ if self._argv:
+ self.infile = self._argv.pop(0)
+ self._in = open(self.infile, 'r')
+ self._stdin = False
+ else:
+ if sys.stdin.isatty():
+ print "### USAGE in __iter__"
+ #self.usage() # Doesn't return
+ return None
+ self.infile = '<stdin>'
+ self._in = sys.stdin
+ self._stdin = True
+ return self
+
+ def next(self):
+ "iterator: get next line, possibly from next file"
+ while True:
+ line = self._in.readline()
+ if line:
+ self.lineno += 1
+ self.linesum += 1
+ return line
+
+ if self._stdin:
+ break
+
+ self._in.close()
+ try:
+ self.infile = self._argv.pop(0)
+ except IndexError:
+ break
+ self.lineno = 0
+ self._in = open(self.infile, 'r')
+
+ self.lineno = -1
+ self.infile = None
+ raise StopIteration
+
+ def getopt(self, shortopts, longopts=[]):
+ "get options and merge into dict 'opt'"
+ try:
+ options, self._argv = getopt.getopt(self._argv, shortopts, longopts)
+ except getopt.GetoptError:
+ print "### USAGE in getopt"
+ #self.usage()
+ return None
+ self.opt.update(dict(options))
+
+ def shift(self):
+ "pop first of remaining arguments (shift)"
+ try:
+ return self._argv.pop(0)
+ except IndexError:
+ #print "### USAGE in shift"
+ #self.usage()
+ return None
+
+
+ def pop(self):
+ "pop last of remaining arguments"
+ try:
+ return self._argv.pop()
+ except IndexError:
+ print "### USAGE in pop"
+ #self.usage()
+ return None
+
+ def warning(self, text):
+ "print warning message to stderr, possibly with filename and lineno"
+ if self.lineno > 0:
+ print >> sys.stderr, '%s:%i: warning: %s' % (self.infile, self.lineno, text)
+ else:
+ print >> sys.stderr, '\nWarning %s: %s\n' % (self.progname, text)
+
+ def error(self, text):
+ "print error message to stderr, possibly with filename and lineno, and exit"
+ if self.lineno > 0:
+ print >> sys.stderr, '%s:%i: %s' % (self.infile, self.lineno, text)
+ else:
+ print >> sys.stderr, '\nError %s: %s\n' % (self.progname, text)
+ sys.exit(1)
+
+ def usage(self):
+ "print usage message, and exit"
+ print >> sys.stderr
+ print >> sys.stderr, self._usage % {'progname': self.progname}
+ print >> sys.stderr
+ #sys.exit(1)
+
+
+if __name__ == '__main__':
+
+ a = Args('Usage: %(progname)s [-a value] [-b value] [-c] word [file...]')
+
+ a.opt['-a'] = 'option a' # set some default option values
+ a.opt['-b'] = 'option b' #
+ a.getopt('a:b:c') # get user supplied option values
+
+ word = a.shift() # get the first of the remaining arguments
+ # use a.pop() to get the last instead
+
+ for line in a: # iterate over the contents of all remaining arguments (file names)
+ if a.lineno == 1:
+ print 'starting new file:', a.infile
+ a.warning(line.rstrip())
+
+ print 'Options:', a.opt
+ print 'Word:', word
+ print 'Total number of lines:', a.linesum
+
+ print 'Command line:', sys.argv # unchanged
+
+ a.warning('warn 1') # print a warning
+ a.error('error') # print an error message and exit
+ a.warning('warn 2') # this won't show
+