Revision bdc080d3acb04ab5f1977c15aa2bda23299e7ea8 authored by Leif Strand on 23 July 2005, 09:02:47 UTC, committed by Leif Strand on 23 July 2005, 09:02:47 UTC
1 parent 5040de8
Raw File
parser.py
#!/usr/bin/env python
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
#<LicenseText>
#=====================================================================
#
#                             CitcomS.py
#                 ---------------------------------
#
#                              Authors:
#            Eh Tan, Eun-seo Choi, and Pururav Thoutireddy 
#          (c) California Institute of Technology 2002-2005
#
#        By downloading and/or installing this software you have
#       agreed to the CitcomS.py-LICENSE bundled with this software.
#             Free for non-commercial academic research ONLY.
#      This program is distributed WITHOUT ANY WARRANTY whatsoever.
#
#=====================================================================
#
#  Copyright June 2005, by the California Institute of Technology.
#  ALL RIGHTS RESERVED. United States Government Sponsorship Acknowledged.
# 
#  Any commercial use must be negotiated with the Office of Technology
#  Transfer at the California Institute of Technology. This software
#  may be subject to U.S. export control laws and regulations. By
#  accepting this software, the user agrees to comply with all
#  applicable U.S. export laws and regulations, including the
#  International Traffic and Arms Regulations, 22 C.F.R. 120-130 and
#  the Export Administration Regulations, 15 C.F.R. 730-744. User has
#  the responsibility to obtain export licenses, or other export
#  authority as may be required before exporting such information to
#  foreign countries or providing access to foreign nationals.  In no
#  event shall the California Institute of Technology be liable to any
#  party for direct, indirect, special, incidental or consequential
#  damages, including lost profits, arising out of the use of this
#  software and its documentation, even if the California Institute of
#  Technology has been advised of the possibility of such damage.
# 
#  The California Institute of Technology specifically disclaims any
#  warranties, including the implied warranties or merchantability and
#  fitness for a particular purpose. The software and documentation
#  provided hereunder is on an "as is" basis, and the California
#  Institute of Technology has no obligations to provide maintenance,
#  support, updates, enhancements or modifications.
#
#=====================================================================
#</LicenseText>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#

"""Citcom input file parser.
(copied and modified from ConfigParser module in Python standard library)

Read and parse input file which consists of 'name=value' pairs. Note that
'name =value', `name= value', or 'name = value' is not allowed, i.e. space
is not allowed on either sides of the eqaul sign. 'name' is case-sensitive.
Blank lines, anything after `#', and just about everything else is ignored.

Intrinsic defaults can be specified by passing them into the constructor as
a dictionary.


class:

Parser -- responsible for for parsing a list of
          input files, and managing the parsed database.

    methods:

    __init__(defaults=None)
        create the parser and specify a dictionary of intrinsic defaults.  The
        keys must be strings, the values must be appropriate for %()s string
        interpolation.

    has_option(option)
        return whether the given option exists.

    options()
        return list of configuration options.

    read(filenames)
        read and parse the list of named configuration files, given by
        name.  A single filename is also allowed.  Non-existing files
        are ignored.

    get(option)
        return a string value for the named option, based on the defaults
        passed into the constructor.

    getstr(option)
        return a string stripped of possible enclosing quotes.

    getint(options)
        like get(), but convert value to an integer.

    getfloat(options)
        like get(), but convert value to a float.

    getintvector(options)
        like get(), but convert value to an integer vector.

    getfloatvector(options)
        like get(), but convert value to a float vector.

    getboolean(options)
        like get(), but convert value to a boolean (currently case
        insensitively defined as 0, false, no, off for 0, and 1, true,
        yes, on for 1).  Returns 0 or 1.

"""
import os, sys, string, types

__all__ = ["NoOptionError", "ParsingError", "Parser"]



# exception classes
class Error(Exception):
    def __init__(self, msg=''):
        self._msg = msg
        Exception.__init__(self, msg)
    def __repr__(self):
        return self._msg
    __str__ = __repr__

class NoOptionError(Error):
    def __init__(self, option):
        Error.__init__(self, "No option `%s'" %
                       option)
        self.option = option

class ParsingError(Error):
    def __init__(self, filename):
        Error.__init__(self, 'File contains parsing errors: %s' % filename)
        self.filename = filename
        self.errors = []

    def append(self, lineno, line):
        self.errors.append((lineno, line))
        self._msg = self._msg + '\n\t[line %2d]: %s' % (lineno, line)


class Parser(object):
    def __init__(self,defaults=None):
        if defaults is None:
            self.__defaults = {}
        else:
            self.__defaults = defaults

    def defaults(self):
        return self.__defaults

    def options(self):
        """Return a list of option names."""
        return self.__options.keys()

    def has_option(self, option):
        """Check for the existence of a given option."""
        return self.__options.has_key(option)

    def read(self, filename):
        """Read and parse a filename."""
        fp = open(filename)
        self.__read(fp, filename)
        fp.close()

    def get(self, option):
        """Get an option value.
        """
        d = self.__defaults.copy()
        d.update(self.__options)
        # Update with the entry specific variables
        try:
            rawval = d[option]
        except KeyError:
            raise NoOptionError(option)

        return rawval

    def __get(self, conv, option):
        return conv(self.get(option))

    def __getvector(self, conv, option):
        val = []
        v = string.split(self.get(option),',')
        try:
            for item in v:
                val.append(conv(item))
            return val
        except TypeError, ValueError:
            raise ValueError, "`%s' is not a vector: %s" % (option, v)

    def getstr(self, option):
        v = self.get(option)
        if v[0] == v[-1] and v[0] in '"\'':
            v = v[1:-1]
        return v

    def getint(self, option):
        return self.__get(int, option)

    def getintvector(self, option):
        return self.__getvector(int, option)

    def getfloat(self, option):
        return self.__get(float, option)

    def getfloatvector(self, option):
        return self.__getvector(float, option)

    def getboolean(self, option):
        states = {'1': 1, 'yes': 1, 'true': 1, 'on': 1,
                  '0': 0, 'no': 0, 'false': 0, 'off': 0}
        v = self.get(option)
        if not states.has_key(string.lower(v)):
            raise ValueError, 'Not a boolean: %s' % v
        return states[string.lower(v)]


    def __read(self, fp, fpname):
        """Parse a un-sectioned setup file.

        key/value options lines, indicated by `name=value' format lines.
        `name =value', `name= value', or `name = value' is not allowed.
        key is case-sensitive. Blank lines, anything after a `#',
        and just about everything else is ignored.
        """
        self.__options = {}
        lineno = 0
        e = None                                  # None, or an exception
        while 1:
            line = fp.readline()
            if not line:
                break
            lineno = lineno + 1
            # blank line?
            if string.strip(line) == '':
                continue
            # remove anything after '#'
            line = string.split(line, '#')[0]

            # key/value pairs can be seperated by whitespaces
            for opt in string.split(line):
                #if opt in string.whitespace:
                #    continue
                keyval = string.split(opt, '=')
                if len(keyval) == 2:
                    self.__options[keyval[0]] = keyval[1]
                else:
                    e = ParsingError(fpname)
                    e.append(lineno, `line`)

        # if any parsing errors occurred, raise an exception
        if e:
            raise e



if __name__ == '__main__':

    if len(sys.argv) != 2:
        import os.path
        print "usage: %s inputfile" % os.path.basename(sys.argv[0])
        sys.exit(1)

    parser = Parser()
    parser.read(sys.argv[1])

    #print parser.options()

    while 1:
        keyin = raw_input('key name: ')
        if keyin:
            for f in (parser.getint, parser.getfloat, parser.getboolean, parser.getstr, parser.getintvector, parser.getfloatvector):
                try:
                    val = None
                    if parser.has_option(keyin):
                        val = f(keyin)
                except (TypeError, ParsingError, ValueError):
                    continue
                print "%s=%s\n" % (keyin, str(val))

        else:
            break


back to top