Skip to content

Commit

Permalink
Update query_config as per #1190
Browse files Browse the repository at this point in the history
Changed all arguments to short names.
Updated printing for most requests, such as shorter compset output,
ordered (alphabetical) compset printing, added 'all' option to compsets
argument, added 'current' to machines argument but maintained previous
behavior. Fixed issue where help didn't print when no arguments were
provided. Also, fixed issue where a bogus value was giving to
compsets and the error message printed wasn't very useful. No we print
available components along with usage.

Fixes #1190
  • Loading branch information
Erich L Foster committed May 5, 2017
1 parent 7a85eaf commit 4f0a70e
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 51 deletions.
2 changes: 1 addition & 1 deletion scripts/lib/CIME/XML/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,6 @@ def print_values(self):
compsets[attrib] = text

logger.info(" %s" %helptext)
for v in compsets.iteritems():
for v in sorted(compsets.iteritems()):
label, definition = v
logger.info(" %20s : %s" %(label, definition))
5 changes: 3 additions & 2 deletions scripts/lib/CIME/XML/compsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,11 @@ def get_value(self, name, attribute=None, resolved=False, subgroup=None):
compsets[alias] = lname
return compsets

def print_values(self):
def print_values(self, help=True):
help_text = self.get_value(name="help")
compsets_text = self.get_value("names")
logger.info(" %s " %help_text)
if help:
logger.info(" %s " %help_text)

logger.info(" --------------------------------------")
logger.info(" Compset Short Name: Compset Long Name ")
Expand Down
2 changes: 1 addition & 1 deletion scripts/lib/CIME/XML/machines.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def list_available_machines(self):
machines.append(mach)
return machines

def probe_machine_name(self):
def probe_machine_name(self, warn=True):
"""
Find a matching regular expression for hostname
in the NODENAME_REGEX field in the file. First match wins.
Expand Down
199 changes: 152 additions & 47 deletions scripts/query_config
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

from Tools.standard_script_setup import *

from CIME.utils import expect
from CIME.utils import expect, get_model
from CIME.XML.files import Files
from CIME.XML.component import Component
from CIME.XML.compsets import Compsets
from CIME.XML.grids import Grids
from CIME.XML.machines import Machines
#from CIME.XML.machines import Machines
import CIME.XML.machines

import argparse, doctest
import re, socket, argparse, doctest

###############################################################################
def query_grids(long_output):
Expand All @@ -18,7 +19,7 @@ def query_grids(long_output):
files = Files()
config_file = files.get_value("GRIDS_SPEC_FILE")
expect(os.path.isfile(config_file),
"Cannot find config_file %s on disk" %config_file)
"Cannot find config_file {} on disk".format(config_file))

grids = Grids(config_file)
if long_output:
Expand All @@ -27,65 +28,86 @@ def query_grids(long_output):
grids.print_values()

###############################################################################
def query_machines():
def query_machines(current=False):
###############################################################################

files = Files()
config_file = files.get_value("MACHINES_SPEC_FILE")
expect(os.path.isfile(config_file),
"Cannot find config_file %s on disk" %config_file)
"Cannot find config_file {} on disk".format(config_file))
# Provide a special machine name indicating no need for a machine name
machines = Machines(config_file,machine="Query")
machines.print_values()
machines.print_values(current_only=current)

###############################################################################
def query_compsets(name):
###############################################################################

# Determine valid component values by checking the value attributes for COMPSETS_SPEC_FILE
files = Files()
components = files.get_components("COMPSETS_SPEC_FILE")
files, components = get_compsets()
match_found = None
for component in components:
if component == name:
match_found = name
break
all = False
if re.search("^all$", name): # print all compsets
model = get_model()
match_found = name
all = True
else:
for component in components:
if component == name:
match_found = name
break

# If name is not a valid argument - exit with error
expect(match_found is not None,
"Invalid input argument %s, valid input arguments are %s" % (name, components))
"Invalid input argument {}, valid input arguments are {}".format(name, components))

# Determine the config_file for the target component
config_file = files.get_value("COMPSETS_SPEC_FILE", attribute={"component":name})
expect((config_file),
"Cannot find any config_component.xml file for %s" %name)
if all: # print all compsets
for component in components:
# the all flag will only print available components
print_config(component, files, all=all)
else:
print_config(name, files)

# Check that file exists on disk
expect(os.path.isfile(config_file),
"Cannot find config_file %s on disk" %config_file)
def print_config(name, files, all=False):
'''
print compsets associated with the component name, but if all is true only
print the details if the associated component is available
'''

# Determine the config_file for the target component
config_file = files.get_value("COMPSETS_SPEC_FILE", attribute={"component":name})
# only error out if we aren't printing all otherwise exit quitely
if not all:
expect((config_file),
"Cannot find any config_component.xml file for {}".format(name))

# Check that file exists on disk
expect(os.path.isfile(config_file),
"Cannot find config_file {} on disk".format(config_file))
elif config_file is None or not os.path.isfile(config_file):
return

print "\nActive component: {}".format(name)
# Now parse the compsets file and write out the compset alias and longname as well as the help text
# determine component xml content
compsets = Compsets(config_file)
compsets.print_values()
# print compsets associated with component without help text
compsets.print_values(help=False)

###############################################################################
def query_component(name):
###############################################################################

# Determine the valid component classes (e.g. atm) for the driver/cpl
# These are then stored in comps_array
files = Files()
infile = files.get_value("CONFIG_CPL_FILE")
config_drv = Component(infile)
components = config_drv.get_valid_model_components()
files, components = get_components()

# Loop through the elements for each component class (in config_files.xml)
# and see if there is a match for the the target component in the component attribute
match_found = False
valid_components = []
for comp in components:
string = "CONFIG_%s_FILE"%comp
string = "CONFIG_{}_FILE".format(comp)

# determine all components in string
components = files.get_components(string)
Expand All @@ -97,16 +119,16 @@ def query_component(name):
if config_file is not None:
match_found = True
expect(os.path.isfile(config_file),
"Cannot find config_file %s on disk" %config_file)
"Cannot find config_file {} on disk".format(config_file))
break

# If name is not a valid argument - exit with error
expect(match_found,
"Invalid input argument %s, valid input arguments are %s" % (name, valid_components))
"Invalid input argument {}, valid input arguments are {}".format(name, valid_components))

# Check that file exists on disk, if not exit with error
expect((config_file),
"Cannot find any config_component.xml file for %s" %name)
"Cannot find any config_component.xml file for {}".format(name))

# determine component xml content
component = Component(config_file)
Expand All @@ -118,49 +140,132 @@ def parse_command_line(args):

cime_model = CIME.utils.get_model()

parser = argparse.ArgumentParser()
parser = ArgumentParser()

CIME.utils.setup_standard_logging_options(parser)

parser.add_argument("--query-compsets-setby",
help="Query compsets that are set by the target component for %s model"%cime_model)
parser.add_argument("--compset",
help="Query compsets that are set by the target component for {} model".format(cime_model))

parser.add_argument("--query-component-name",
help="Query component settings that are set by the target component for %s model"%cime_model)
parser.add_argument("--component",
help="Query component settings that are set by the target component for {} model".format(cime_model))

parser.add_argument("--query-grids", action="store_true",
help="Query supported model grids for %s model" %cime_model)
parser.add_argument("--grids", action="store_true",
help="Query supported model grids for {} model".format(cime_model))

parser.add_argument("--grids-alias",
help="Query model grids for input grid alias for %s model - not implemented yet" %cime_model)
# what was the intent of this argument?
# parser.add_argument("--grids-alias",
# help="Query model grids for input grid alias for {} model - not implemented yet".format(cime_model))

parser.add_argument("--query-machines", action="store_true",
help="Query supported machines for %s model" %cime_model)
parser.add_argument("--machines", nargs='?', action='store', const=True, choices=['current', 'empty'],
help="Query supported machines for {} model".format(cime_model))

parser.add_argument("--long", action="store_true",
help="Provide long output for queries")

args = CIME.utils.parse_args_and_handle_standard_logging_options(args, parser)

# make sure at least one argument has been passed
if not (args.grids or args.compset or args.component or args.machines):
parser.print_help(sys.stderr)

CIME.utils.handle_standard_logging_options(args)

return args

def get_compsets():
'''
Determine valid component values by checking the value attributes for COMPSETS_SPEC_FILE
'''
files = Files()
return files, files.get_components("COMPSETS_SPEC_FILE")

def get_components():
'''
Determine the valid component classes (e.g. atm) for the driver/cpl
These are then stored in comps_array
'''
files = Files()
infile = files.get_value("CONFIG_CPL_FILE")
config_drv = Component(infile)
return files, config_drv.get_valid_model_components()

# we override the error message from ArgumentParser to have a more helpful
# message in the case of missing arguments
class ArgumentParser(argparse.ArgumentParser):

def error(self, message):
self.print_usage(sys.stderr)
# missing argument
if "expected one argument" in message:
if "compset" in message:
files, components = get_compsets()
self.exit(2, '{}: error: {}\nValid input arguments are {}\n'
.format(self.prog, message, components))
elif "component" in message:
files, components = get_components()
self.exit(2, '{}: error: {}\nValid input arguments are {}\n'
.format(self.prog, message, components))
# for all other errors
self.exit(2, '{}: error: {}\n'.format(self.prog, message))

# we overide print_values from Machines to add current in machine description
class Machines(CIME.XML.machines.Machines):

def print_values(self, current_only=False):
# write out machines
if current_only and not self.probe_machine_name(warn=False):
print "Current machine is not listed in config file: {}".format(config_file)
else:
machines = self.get_nodes(nodename="machine")
print "Machines"
for machine in machines:
name = machine.get("MACH")
desc = machine.find("DESC")
os_ = machine.find("OS")
compilers = machine.find("COMPILERS")
max_tasks_per_node = machine.find("MAX_TASKS_PER_NODE")
pes_per_node = machine.find("PES_PER_NODE")

current_machine = self.probe_machine_name(warn=False)
if current_machine and current_machine in name:
print " {} : {} ".format(name + " (current)", desc.text)
print " os ", os_.text
print " compilers ",compilers.text
if pes_per_node is not None:
print " pes/node ",pes_per_node.text
if max_tasks_per_node is not None:
print " max_tasks/node ",max_tasks_per_node.text
elif not current_only:
print " {} : {} ".format(name, desc.text)
print " os ", os_.text
print " compilers ",compilers.text
if pes_per_node is not None:
print " pes/node ",pes_per_node.text
if max_tasks_per_node is not None:
print " max_tasks/node ",max_tasks_per_node.text

###############################################################################
def _main_func():
###############################################################################

args = parse_command_line(sys.argv)

if args.query_grids:
if args.grids:
query_grids(long_output=args.long)

if args.query_compsets_setby:
query_compsets(name=args.query_compsets_setby)
if args.compset:
query_compsets(name=args.compset)

if args.query_component_name:
query_component(args.query_component_name)
if args.component:
query_component(args.component)

if args.query_machines:
# this order is required since booleans are not iterable
if args.machines is not None and args.machines is True:
query_machines()
elif args.machines is not None and 'current' in args.machines:
query_machines(current=True)


###############################################################################

Expand Down

0 comments on commit 4f0a70e

Please sign in to comment.