예제 #1
0
def parse_host_model_files(host_filenames, preproc_defs, host_name, logger):
    ###############################################################################
    """
    Gather information from host files (e.g., DDTs, registry) and
    return a host model object with the information.
    """
    header_dict = {}
    table_dict = {}
    known_ddts = list()
    for filename in host_filenames:
        logger.info('Reading host model data from {}'.format(filename))
        # parse metadata file
        mtables = parse_metadata_file(filename, known_ddts, logger)
        fort_file = find_associated_fortran_file(filename)
        ftables = parse_fortran_file(fort_file,
                                     preproc_defs=preproc_defs,
                                     logger=logger)
        # Check Fortran against metadata (will raise an exception on error)
        mheaders = list()
        for sect in [x.sections() for x in mtables]:
            mheaders.extend(sect)
        # end for
        fheaders = list()
        for sect in [x.sections() for x in ftables]:
            fheaders.extend(sect)
        # end for
        check_fortran_against_metadata(mheaders, fheaders, filename, fort_file,
                                       logger)
        # Check for duplicate tables, then add to dict
        for table in mtables:
            if table.table_name in table_dict:
                duplicate_item_error(table.table_name, filename,
                                     table.table_type,
                                     table_dict[header.title])
            else:
                table_dict[table.table_name] = table
            # end if
        # end for
        # Check for duplicate headers, then add to dict
        for header in mheaders:
            if header.title in header_dict:
                duplicate_item_error(header.title, filename,
                                     header.header_type,
                                     header_dict[header.title])
            else:
                header_dict[header.title] = header
                if header.header_type == 'ddt':
                    known_ddts.append(header.title)
            # end if
        # end for
    # end for
    if not host_name:
        host_name = None
    # end if
    host_model = HostModel(table_dict, host_name, logger)
    return host_model
예제 #2
0
def parse_scheme_files(scheme_filenames, preproc_defs, logger):
    ###############################################################################
    """
    Gather information from scheme files (e.g., init, run, and finalize
    methods) and return resulting dictionary.
    """
    table_dict = {}  # Duplicate check and for dependencies processing
    header_dict = {}  # To check for duplicates
    known_ddts = list()
    for filename in scheme_filenames:
        logger.info('Reading CCPP schemes from {}'.format(filename))
        # parse metadata file
        mtables = parse_metadata_file(filename, known_ddts, logger)
        fort_file = find_associated_fortran_file(filename)
        ftables = parse_fortran_file(fort_file,
                                     preproc_defs=preproc_defs,
                                     logger=logger)
        # Check Fortran against metadata (will raise an exception on error)
        mheaders = list()
        for sect in [x.sections() for x in mtables]:
            mheaders.extend(sect)
        # end for
        fheaders = list()
        for sect in [x.sections() for x in ftables]:
            fheaders.extend(sect)
        # end for
        check_fortran_against_metadata(mheaders, fheaders, filename, fort_file,
                                       logger)
        # Check for duplicate tables, then add to dict
        for table in mtables:
            if table.table_name in table_dict:
                duplicate_item_error(table.table_name, filename,
                                     table.table_type,
                                     table_dict[header.title])
            else:
                table_dict[table.table_name] = table
            # end if
        # end for
        # Check for duplicate headers, then add to dict
        for header in mheaders:
            if header.title in header_dict:
                duplicate_item_error(header.title, filename,
                                     header.header_type,
                                     header_dict[header.title])
            else:
                header_dict[header.title] = header
                if header.header_type == 'ddt':
                    known_ddts.append(header.title)
                # end if
            # end if
        # end for
    # end for
    return header_dict.values(), table_dict
예제 #3
0
def parse_fortran_files(filenames, run_env, output_dir, sep, logger):
    ###############################################################################
    """
    Parse each file in <filenames> and produce a prototype metadata file
    with a metadata table for each arg_table entry in the file.
    """
    meta_filenames = list()
    for filename in filenames:
        logger.info('Looking for arg_tables from {}'.format(filename))
        reset_standard_name_counter()
        ftables = parse_fortran_file(filename, run_env)
        # Create metadata filename
        filepath = '.'.join(os.path.basename(filename).split('.')[0:-1])
        fname = filepath + '.meta'
        mfilename = os.path.join(output_dir, fname)
        write_metadata_file(mfilename, ftables, sep)
        meta_filenames.append(mfilename)
    return meta_filenames
예제 #4
0
def convert_file(filename_in, filename_out, metadata_filename_out, logger=None):
    """Convert a file's old metadata to the new format
    Note that only the bare minimum error checking is done.
    """
    current_module = None
    # First, suck in the old file
    do_convert = True
    if not os.path.exists(filename_in):
        raise IOError("convert_file: file, '{}', does not exist".format(filename_in))
    # End if
    if os.path.exists(filename_out):
        raise IOError("convert_file: file, '{}', already exists".format(filename_out))
    # End if
    # End if
    # Read all lines of the file at once
    with open(filename_in, 'r') as file:
        fin_lines = file.readlines()
        for index in xrange(len(fin_lines)):
            fin_lines[index] = fin_lines[index].rstrip('\n')
        # End for
    # End with
    max_line = len(fin_lines) - 1
    mdconfig = list()
    in_preamble = True
    in_type = False
    with open(filename_out, 'w') as file:
        line, lindex = next_line(fin_lines, max_line)
        while line is not None:
            # Check for a module line
            current_module = parse_module_line(line, current_module)
            # Maintain a status of being in a DDT definition
            if (not in_type) and type_re.match(line):
                in_type = True
            elif in_type and end_type_re.match(line):
                in_type = False
            # End if
            # Check for end of preamble
            if (not in_type) and (line.lstrip()[0:8].lower() == 'contains'):
                in_preamble = False
            # End if
            # Check for beginning of new table
            words = line.split()
            # This is case sensitive
            if len(words) > 2 and words[0] in ['!!', '!>'] and '\section' in words[1] and 'arg_table_' in words[2]:
                # We have a new table, parse the header
                table_name = words[2].replace('arg_table_','')
##XXgoldyXX: Uncomment this after conversion is over
#                logger.info('Found old metadata table, {}, on line {}'.format(table_name, lindex+1))
                # The header line is not modified
                file.write(line+"\n")
                # Write an include line for the metadata table
                file.write('!! \htmlinclude {}.html\n'.format(table_name))
                # Create the table start section
                mdtable = MetadataTable(table_name, current_module)
                mdconfig.append(mdtable)
                line, lindex = next_line(fin_lines, max_line, cindex=lindex)
                words = line.split('|')
                header_locs = {}
                dim_names = [__not_found__]*15
                # Do not work on a blank table
                if len(words) > 1:
                    table_header = [x.strip() for x in words[1:-1]]
                    for ind in xrange(len(table_header)):
                        header_locs[table_header[ind]] = ind
                    # End for
                    # Find the local_name index (exception if not found)
                    local_name_ind = header_locs['local_name']
                    # The table header line is not output
                    line, lindex = next_line(fin_lines, max_line, cindex=lindex)
                    # This is the delimiter line, do not output
                    # Parse the entries
                    while len(words) > 1:
                        line, lindex = next_line(fin_lines, max_line, cindex=lindex)
                        words = line.split('|')
                        if len(words) <= 1:
                            # End of table, just write and continue
                            file.write(line+'\n')
                            continue
                        # End if
                        entries = [x.strip() for x in words[1:-1]]
                        # Okay, one check
                        if len(entries) != len(header_locs):
                            raise ValueError("Malformed table entry")
                        # End if
                        # First output the local name
                        var_name = entries[local_name_ind]
                        # Strip old-style DDT references
                        var_name = var_name[var_name.rfind('%')+1:]
                        mdobj = MetadataEntry(var_name)
                        mdtable[var_name] = mdobj
                        # Now, create the rest of the entries
                        for ind in xrange(len(entries)):
                            attr_name = table_header[ind]
                            entry = entries[ind]
                            if attr_name == 'local_name':
                                # Already handled this
                                continue
                            elif attr_name == 'rank':
                                attr_name = 'dimensions'
                                rank = int(entry)
                                entry = '(' + ','.join(dim_names[0:rank]) + ')'
                            elif attr_name == 'standard_name':
                                # The standard name needs to be lowercase
                                std_name = entry.lower()
                                # Standard names cannot have dashes
                                std_name = std_name.replace('-', '_')
                                # Standard names cannot have periods
                                std_name = std_name.replace('.', '_')
                                entries[ind] = std_name
                                entry = std_name
                            elif attr_name == 'intent':
                                if in_preamble:
                                    entry = ''
                                elif entry.lower() == 'none':
                                    if logger is None:
                                        raise ValueError("{} has intent = none in {}".format(var_name, table_name))
                                    else:
                                        logger.warning("{} has intent = none in {}".format(var_name, table_name))
                                    # End if
                                # End if
                            # No else needed
                            # End if
                            # Add attribute
                            if (len(entry) > 0) or (attr_name in required_attrs):
                                mdobj[attr_name] = entry
                            # End if
                        # End for (done with entry)
                    # End while (done with table)
                else:
                    # Just write the line (should be a table ending)
                    if line.strip() != '!!':
                        raise ValueError("All tables must end with !! line")
                    # End if
                    file.write(line+'\n')
                # End if (blank table)
            else:
                # Not a table, just write and continue
                file.write(line+'\n')
            # End if
            # Always load a new line
            line, lindex = next_line(fin_lines, max_line, cindex=lindex)
        # End while
    # End with (file)
    # Read in the Fortran source to find dimension information
    mheaders = parse_fortran_file(filename_out, preproc_defs={'CCPP':1, 'HYBRID':1}, logger=logger)
    # Find and replace dimension information for each metadata header
    for table in mdconfig:
        # Find matching Fortran header
        mheader = None
        for mh in mheaders:
            if mh.title == table.name:
                mheader = mh
                break
            # End if
        # End for
        if mheader is None:
            if logger is not None:
                logger.warning('WARNING: Cannot find {} in {} for dimension translation'.format(table.name, filename_out))
            # End if
            continue # Skip this table
        # End for
        # The Fortran table does not have valid standard names so
        # organize them by local name.
        header_vars = {}
        for var in mheader.variable_list():
            header_vars[var.get_prop_value('local_name').lower()] = var
        # End for
        for lname in table.keys():
            var = table[lname]
            if lname.lower() in header_vars:
                fvar = header_vars[lname.lower()]
            else:
                if logger is not None:
                    logger.warning('WARNING: Cannot find variable {} in {} ({}), skipping dimension translation'.format(lname, table.name, filename_out))
                # End if
                fvar = None
            # End if
            dimstring = var['dimensions'].strip().lstrip('(').rstrip(')')
            if ':' in dimstring: # i.e., this not a scalar variable
                dims = dimstring.split(',')
                rank = len(dims)
                if fvar is None:
                    fdims = None
                else:
                    fdims = fvar.get_dimensions()
                # End if
                if fdims is None:
                    # We are dealing with an invalid variable, deal with it
                    dims = [__not_found__]*rank
                else:
                    dims = list()
                    for fdim in fdims:
                        fdlist = fdim.split(':')
                        fdlen = len(fdlist)
                        dlist = ['']*fdlen
                        for index in xrange(fdlen):
                            # For each dimension component, find the standard_name
                            # First, see if it is blank, then integer, then var
                            fd = fdlist[index]
                            if len(fd) == 0:
                                fdnum = ''
                            else:
                                fdnum = None
                            # End if
                            if len(fd) > 0:
                                try:
                                    test = int(fd)
                                    fdnum = fd
                                except Exception as e:
                                    pass
                                # End try
                            # End if
                            if (len(fd) > 0) and (fdnum is None):
                                # Try to find the standard name for this item
                                if table.has(fd):
                                    fdvar = table.get(fd)
                                    fdnum = fdvar['standard_name']
                                else:
                                    if logger is not None:
                                        logger.warning('WARNING: No local variable found for dimension, {} in {}'.format(fd, lname))
                                    # End if
                                    fdnum = 'XXnot_foundXX'
                                # End if
                            # End if
                            dlist[index] = fdnum
                        # End for
                        # Reassemble dim
                        dims.append(':'.join(dlist))
                    # End for
                # End if
                # Reset dimensions
                var['dimensions'] = '(' + ','.join(dims) + ')'
            # End if
        # End for
    # End for
    # Write out finalized metadata file
    with open(metadata_filename_out, 'w') as mdfile:
        spacer = ""
        for table in mdconfig:
            if len(spacer) > 0:
                mdfile.write(spacer)
            # End if
            table.write(mdfile)
            spacer = '\n'+72*'#'+'\n'