Пример #1
0
    def addNamelist(self, name, full_name, variable_list, trigger=None):
        """ Adds a namelist to the input file that will be parsed. Variable list
          must be an array of arrays. Each array element must be an array that
          has the information [varname, datatype, default, chars to match]. The
          'trigger' is the logical variable that gets set to true if this
          namelist is specified in the input file.
        """

        if name in self.ordered_namelist_keys:
            raise InputError('Namelist %s defined multiple times' % name)

        self.ordered_namelist_keys.append(name)
        self.namelists[name] = Namelist(trigger, full_name)

        for var in variable_list:

            if not isinstance(var, (list, tuple)) or len(var) not in [4, 5]:
                raise InputError(
                    'variables in variable_list must be lists of ' +
                    'length 4 or 5. [varname, datatype, default, description, internal_datatype ('
                    'Optional)]')
            if len(var) == 4:
                self.namelists[name].addVariable(var[0], var[1], var[2],
                                                 var[3])
            else:
                self.namelists[name].addVariable(var[0], var[1], var[2],
                                                 var[3], var[4])
Пример #2
0
    def __init__(self,
                 varname,
                 dat_type=int,
                 default=None,
                 chars_to_match=4,
                 case_sensitive=False,
                 description=''):
        """ Initializes the variable type. Sets the default value as well as
          specifying how many characters are required by the parser to trigger
          recognition
      """
        # Catch illegalities
        if not dat_type in (int, str, float):
            raise InputError('Variable has unknown data type %s' %
                             dat_type.__name__)

        # You can't match more characters than you have characters!
        chars_to_match = min(chars_to_match, len(varname))

        self.name = varname
        self.datatype = dat_type
        if default is not None:
            if self.datatype is str:
                self.value = default.replace("'", '').replace('"', '')
            else:
                self.value = self.datatype(default)
        else:
            self.value = None
        self.tomatch = chars_to_match
        self.case_sensitive = case_sensitive
        self.description = description
Пример #3
0
    def Open(self):
        """ Signifies that the namelist is open """
        if self.open:
            raise InputError('Namelist already open. Cannot open before closing')

        if self.trigger: self.variables[self.trigger] = True
        self.open = True
Пример #4
0
    def _full_namelist_name(self, nml):
        """ Determines what the full namelist name is. We try to make as many
          allowances as possible. We will match the first 3 characters and
          replace all _'s with
      """
        nml = nml.replace(' ', '_')  # replaces spaces with _'s
        for key in self.ordered_namelist_keys:
            if self.namelists[key] == nml: return key

        raise InputError('Unrecognized namelist %s' % nml)
Пример #5
0
    def __init__(self,
                 varname,
                 dat_type=int,
                 default=None,
                 description='',
                 int_dat_type=str):
        """ Initializes the variable type. Sets the default value as well as
          specifying how many characters are required by the parser to trigger
          recognition
        """
        # Catch illegalities
        if dat_type not in (int, str, float, list, tuple):
            raise InputError('Variable has unknown data type %s' %
                             dat_type.__name__)
        if int_dat_type not in (int, str, float):
            raise InputError('Variable has unknown internal data type %s' %
                             int_dat_type)

        self.name = varname
        self.datatype = dat_type
        self.int_datatype = int_dat_type
        if default is None:
            self.value = None
        elif self.datatype is str:
            self.value = default.replace("'", '').replace('"', '')
        elif self.datatype in [list, tuple]:
            if isinstance(default, str):
                self.value = [
                    self.int_datatype(x.strip())
                    for x in re.split(';\s*|,\s*', default.replace('"', ''))
                ]
            else:
                self.value = default
        else:
            self.value = self.datatype(default)
        self.description = description
Пример #6
0
    def Parse(self, filename):
        """
        This subroutine parses the input file. Only data in namelists are
          parsed, and all namelists must be set prior to calling this routine.

          It will create a dictionary of Input variables for all variables in
          all namelists. They all flood the same namespace. If there are any
          conflicts between variables in namelists, an error will be raised.
          Make sure all input variables are unique!
        """
        from os.path import exists

        # Make sure our file exists

        if filename is None:
            raise InputError("No input file was provided!")
        if not exists(filename):
            raise InputError("Can't find input file (%s)" % filename)

        # Load the whole thing into memory. This should be plenty short enough.
        lines = open(filename, 'r').readlines()

        # Save the text of the input file so we can echo it back later
        self.text = ''.join(lines)

        # We will loop through the input file three times:
        #
        # 1st: Load all of the data into an array (namelist_fields)
        # 2nd: Combine multi-element values (to allow commas in input variables)
        # 3rd: Loop through the fields to change the values of the variables.

        declared_namelists = [
        ]  # keep track of the namelists we've found so far
        namelist_fields = []  # entries in a given namelist
        innml = False  # are we in a namelist now? Don't enter multiple

        # split up the input file into separate fields by comma

        for line in lines:
            # Skip title lines (we are flexible here) and comments
            if not innml and not line.strip().startswith('&'):
                continue
            if line.strip().startswith('#') or line.strip().startswith('!'):
                continue

            # Catch some errors
            if innml and line.strip().startswith('&'):
                raise InputError(
                    'Invalid input. Terminate each namelist prior ' +
                    'to starting another one.')

            # End of a namelist
            elif innml and line.strip() in ['/', '&end']:
                innml = False

            # Now if we finally find a namelist
            elif not innml and line.strip().startswith('&'):
                innml = True
                namelist = line.strip()[1:].lower()
                namelist = self._full_namelist_name(namelist)

                if namelist in declared_namelists:
                    raise InputError('Namelist %s specified multiple times' %
                                     namelist)

                self.namelists[namelist].Open()
                declared_namelists.append(namelist)
                namelist_fields.append([])

            # We are in a namelist here, now fill in the fields
            elif innml:
                items = line.strip().split(',')

                # Screen any blank fields
                j = 0
                while j < len(items):
                    items[j] = items[j].strip()
                    if len(items[j]) == 0:
                        items.pop(j)
                    else:
                        j += 1

                namelist_fields[len(namelist_fields) - 1].extend(items)

            # end if [elif innml]

        # end for line in lines

        # Combine any multi-element fields into the last field that has a = in it

        begin_field = -1
        for i in range(len(namelist_fields)):
            for j in range(len(namelist_fields[i])):
                if not '=' in namelist_fields[i][j]:
                    if begin_field == -1:
                        raise InputError('Invalid input file! Error reading ' +
                                         'namelist %s' % declared_namelists[i])
                    else:
                        namelist_fields[i][begin_field] += \
                            ',%s' % namelist_fields[i][j]
                else:
                    begin_field = j

        # Now parse through the items to add them to the master dictionary. Note
        # that thanks to the last step, all data in namelist_fields will be
        # contained within fields that have a '='. All others can be ignored

        for i in range(len(namelist_fields)):
            for j in range(len(namelist_fields[i])):

                if not '=' in namelist_fields[i][j]:
                    continue
                else:
                    var = namelist_fields[i][j].split('=')
                    var[0] = var[0].strip()
                    var[1] = var[1].strip()

                    # Now we have to loop through all variables in that namelist to
                    # see if this is the variable we want.

                    found = False
                    for key in list(self.namelists[
                            declared_namelists[i]].variables.keys()):
                        if self.namelists[declared_namelists[i]].variables[key] == \
                                var[0]:
                            self.namelists[declared_namelists[i]].variables[key]. \
                                SetValue(var[1])
                            found = True
                            break

                    if not found:
                        raise InputError('Unknown variable %s in &%s' %
                                         (var[0], declared_namelists[i]))

        # Now it's time to fill the INPUT dictionary

        INPUT = {}

        for nml in self.ordered_namelist_keys:
            for var in list(self.namelists[nml].variables.keys()):

                # Here, the triggers are just bool types, so protect from accessing
                # an attribute that doesn't exist! We only allow Variable types and
                # bool types

                var_object = self.namelists[nml].variables[var]
                try:
                    INPUT[var] = self.namelists[nml].variables[var].value
                except AttributeError:
                    if isinstance(var_object, bool):
                        INPUT[var] = var_object
                    else:
                        raise InputError('Disallowed namelist variable type')

        return INPUT