From f0dc1f917db3303fdaf6a993c7b969547fe13c02 Mon Sep 17 00:00:00 2001 From: Erich L Foster Date: Tue, 2 May 2017 13:59:57 -0600 Subject: [PATCH] Added Ability to Query Single Machine In this commit-- added the ability to give machine name as a query. Additionally, fixed some the argument descriptions. Also, fixed argument descriptions to be more descriptive on choices. Test suite: `scripts_regression_tests.py` and ``` ./query_config ./query_config --grids ./query_config --machines ./query_config --machines current ./query_config --machines redsky ./query_config --machines edison ./query_config --machines skybridge ./query_config --compsets ./query_config --compsets all ./query_config --compsets drv ./query_config --component ``` Test baseline: Test namelist changes: Test status: bit for bit Fixes #1155, #1190 User interface changes?: manage_case -> query_config --compset -> --compsets --machine -> --machines added 'all' option for --compsets added 'current' and to --machines Code review: @billsacks, @jgfouca --- scripts/lib/CIME/XML/compsets.py | 10 ++-- scripts/lib/CIME/XML/machines.py | 17 +++--- scripts/query_config | 94 +++++++++++++++++++++++--------- 3 files changed, 83 insertions(+), 38 deletions(-) diff --git a/scripts/lib/CIME/XML/compsets.py b/scripts/lib/CIME/XML/compsets.py index 70a0a6cf7f7..fe747ed19b7 100644 --- a/scripts/lib/CIME/XML/compsets.py +++ b/scripts/lib/CIME/XML/compsets.py @@ -42,7 +42,7 @@ def get_compset_match(self, name): user_mods = user_mods_node.text else: user_mods = None - logger.debug("Found node match with alias: %s and lname: %s" % (alias, lname)) + logger.debug("Found node match with alias: {} and lname: {}".format(alias, lname)) return (lname, alias, science_support, user_mods) return (None, None, [False], None) @@ -72,7 +72,7 @@ def get_value(self, name, attribute=None, resolved=False, subgroup=None): nodes = self.get_nodes(nodename="compset") for node in nodes: for child in node: - logger.debug ("Here child is %s with value %s"%(child.tag,child.text)) + logger.debug ("Here child is {} with value {}".format(child.tag,child.text)) if child.tag == "alias": alias = child.text if child.tag == "lname": @@ -84,11 +84,11 @@ def print_values(self, help=True): help_text = self.get_value(name="help") compsets_text = self.get_value("names") if help: - logger.info(" %s " %help_text) + logger.info(" {} ".format(help_text)) logger.info(" --------------------------------------") - logger.info(" Compset Short Name: Compset Long Name ") + logger.info(" Compset Alias: Compset Long Name ") logger.info(" --------------------------------------") for v in compsets_text.iteritems(): label, definition = v - logger.info(" %20s : %s" %(label, definition)) + logger.info(" {:20} : {}".format(label, definition)) diff --git a/scripts/lib/CIME/XML/machines.py b/scripts/lib/CIME/XML/machines.py index addc4fae18f..de31b9b1875 100644 --- a/scripts/lib/CIME/XML/machines.py +++ b/scripts/lib/CIME/XML/machines.py @@ -29,7 +29,7 @@ def __init__(self, infile=None, files=None, machine=None): if infile is None: infile = files.get_value("MACHINES_SPEC_FILE") schema = files.get_schema("MACHINES_SPEC_FILE") - logger.debug("Verifying using schema %s"%schema) + logger.debug("Verifying using schema {}".format(schema)) self.machines_dir = os.path.dirname(infile) @@ -38,7 +38,7 @@ def __init__(self, infile=None, files=None, machine=None): # Append the contents of $HOME/.cime/config_machines.xml if it exists # This could cause problems if node matchs are repeated when only one is expected local_infile = os.path.join(os.environ.get("HOME"),".cime","config_machines.xml") - logger.debug("Infile: %s" , local_infile) + logger.debug("Infile: {}" , local_infile) if os.path.exists(local_infile): GenericXML.read(self, local_infile, schema) @@ -48,7 +48,7 @@ def __init__(self, infile=None, files=None, machine=None): else: machine = self.probe_machine_name() - expect(machine is not None, "Could not initialize machine object from %s or %s" % (infile, local_infile)) + expect(machine is not None, "Could not initialize machine object from {} or {}".format(infile, local_infile)) self.set_machine(machine) def get_machines_dir(self): @@ -113,7 +113,8 @@ def probe_machine_name(self, warn=True): names_not_found_quoted = ["'" + name + "'" for name in names_not_found] names_not_found_str = ' or '.join(names_not_found_quoted) - logger.warning("Could not find machine match for %s" % names_not_found_str) + if warn: + logger.warning("Could not find machine match for {}".format(names_not_found_str)) return machine @@ -136,7 +137,7 @@ def _probe_machine_name_one_guess(self, nametomatch): logger.debug("machine regex string is " + regex_str) regex = re.compile(regex_str) if regex.match(nametomatch): - logger.debug("Found machine: %s matches %s" % (machtocheck, nametomatch)) + logger.debug("Found machine: {} matches {}".format(machtocheck, nametomatch)) machine = machtocheck break @@ -158,7 +159,7 @@ def set_machine(self, machine): self.machine = machine elif self.machine != machine or self.machine_node is None: self.machine_node = self.get_optional_node("machine", {"MACH" : machine}) - expect(self.machine_node is not None, "No machine %s found" % machine) + expect(self.machine_node is not None, "No machine {} found".format(machine)) self.machine = machine return machine @@ -274,7 +275,7 @@ def has_batch_system(self): batch_system = self.get_optional_node("BATCH_SYSTEM", root=self.machine_node) if batch_system is not None: result = (batch_system.text is not None and batch_system.text != "none") - logger.debug("Machine %s has batch: %s" % (self.machine, result)) + logger.debug("Machine {} has batch: {}".format(self.machine, result)) return result def get_suffix(self, suffix_type): @@ -298,7 +299,7 @@ def print_values(self): max_tasks_per_node = machine.find("MAX_TASKS_PER_NODE") pes_per_node = machine.find("PES_PER_NODE") - print " %s : %s "% (name , desc.text) + print " {} : {} ".format(name , desc.text) print " os ", os_.text print " compilers ",compilers.text if pes_per_node is not None: diff --git a/scripts/query_config b/scripts/query_config index bc063726631..42b8a278f19 100755 --- a/scripts/query_config +++ b/scripts/query_config @@ -28,7 +28,7 @@ def query_grids(long_output): grids.print_values() ############################################################################### -def query_machines(current=False): +def query_machines(machine_name=None): ############################################################################### files = Files() @@ -36,8 +36,8 @@ def query_machines(current=False): expect(os.path.isfile(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(current_only=current) + machines = Machines(config_file, machine="Query") + machines.print_values(machine_name=machine_name) ############################################################################### def query_compsets(name): @@ -144,11 +144,26 @@ def parse_command_line(args): CIME.utils.setup_standard_logging_options(parser) - parser.add_argument("--compset", - help="Query compsets that are set by the target component for {} model".format(cime_model)) + files, components = get_compsets() + valid_components = ['all'] + for item in components: + valid_components.append(item) - parser.add_argument("--component", - help="Query component settings that are set by the target component for {} model".format(cime_model)) + parser.add_argument("--compsets", nargs='?', const='all', choices=valid_components, + help="Query compsets corresponding to the target component for the {} model".format(cime_model)) + + files, components = get_components() + # Loop through the elements for each component class (in config_files.xml) + valid_components = [] + for comp in components: + string = "CONFIG_{}_FILE".format(comp) + + # determine all components in string + components = files.get_components(string) + for item in components: + valid_components.append(item) + parser.add_argument("--component", choices=valid_components, + help="Query component settings corresponding to the target component for {} model".format(cime_model)) parser.add_argument("--grids", action="store_true", help="Query supported model grids for {} model".format(cime_model)) @@ -157,8 +172,18 @@ def parse_command_line(args): # parser.add_argument("--grids-alias", # help="Query model grids for input grid alias for {} model - not implemented yet".format(cime_model)) - parser.add_argument("--machines", nargs='?', action='store', const=True, choices=['current', 'empty'], - help="Query supported machines for {} model".format(cime_model)) + config_file = files.get_value("MACHINES_SPEC_FILE") + expect(os.path.isfile(config_file), + "Cannot find config_file {} on disk".format(config_file)) + machines = Machines(config_file, machine="Query") + machines = machines.get_nodes(nodename="machine") + machine_names = ['current'] + for machine in machines: + machine_names.append(machine.get("MACH")) + parser.add_argument("--machines", nargs='?', action='store', const=True, choices=machine_names, + help="Query supported machines for {} model." + " If option is left empty then all machines are listed," + " if current is giving the current machine details are listed.".format(cime_model)) parser.add_argument("--long", action="store_true", help="Provide long output for queries") @@ -166,7 +191,7 @@ def parse_command_line(args): args = parser.parse_args() # make sure at least one argument has been passed - if not (args.grids or args.compset or args.component or args.machines): + if not (args.grids or args.compsets or args.component or args.machines): parser.print_help(sys.stderr) CIME.utils.handle_standard_logging_options(args) @@ -204,21 +229,40 @@ class ArgumentParser(argparse.ArgumentParser): .format(self.prog, message, components)) elif "component" in message: files, components = get_components() + # Loop through the elements for each component class (in config_files.xml) + valid_components = [] + for comp in components: + string = "CONFIG_{}_FILE".format(comp) + + # determine all components in string + components = files.get_components(string) + for item in components: + valid_components.append(item) self.exit(2, '{}: error: {}\nValid input arguments are {}\n' - .format(self.prog, message, components)) + .format(self.prog, message, valid_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) + def print_values(self, machine_name=None): + # set flag to look for single machine + if machine_name is not None: + single_machine = True + if machine_name == 'current': + machine_name = self.probe_machine_name(warn=False) else: + single_machine = False + + # if we can't find the specified machine + if single_machine and machine_name is None: + files = Files() + config_file = files.get_value("MACHINES_SPEC_FILE") + print "Machine is not listed in config file: {}".format(config_file) + else: # write out machines machines = self.get_nodes(nodename="machine") - print "Machines" + print "Machine(s)" for machine in machines: name = machine.get("MACH") desc = machine.find("DESC") @@ -228,15 +272,16 @@ class Machines(CIME.XML.machines.Machines): 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) + if not single_machine: + name += " (current)" if current_machine and current_machine in name else "" + 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 - elif not current_only: + elif single_machine and machine_name in name: print " {} : {} ".format(name, desc.text) print " os ", os_.text print " compilers ",compilers.text @@ -254,17 +299,16 @@ def _main_func(): if args.grids: query_grids(long_output=args.long) - if args.compset: - query_compsets(name=args.compset) + if args.compsets: + query_compsets(name=args.compsets) if args.component: query_component(args.component) - # this order is required since booleans are not iterable - if args.machines is not None and args.machines is True: + if args.machines is not None and args.machines is True: # print all machines query_machines() - elif args.machines is not None and 'current' in args.machines: - query_machines(current=True) + elif args.machines is not None: # print the selected machine + query_machines(machine_name=args.machines) ###############################################################################