Repository: ESMCI/cime

Issue:
xmlquery reading wrong group from env_batch
The group element in env_batch.xml canbe ignored, instead use the job element as group.
Use set_value as template and change get_value(s).



Discussion:

Resolving patch:
diff --git a/utils/python/CIME/XML/env_batch.py b/utils/python/CIME/XML/env_batch.py
--- a/utils/python/CIME/XML/env_batch.py
+++ b/utils/python/CIME/XML/env_batch.py
@@ -10,6 +10,8 @@
 from CIME.utils import convert_to_string, transform_vars, get_cime_root
 from copy import deepcopy
 
+import re
+
 logger = logging.getLogger(__name__)
 
 class EnvBatch(EnvBase):
@@ -84,10 +86,12 @@ def get_values(self, item, attribute=None, resolved=True, subgroup=None):
 
         nodes   = [] # List of identified xml elements
         results = [] # List of identified parameters
-
+             
+        
         # Find all nodes with attribute name and attribute value item
         # xpath .//*[name='item']
         # for job in self.get_nodes("job") :
+        
         groups = self.get_nodes("group")
 
         for group in groups :
@@ -101,36 +105,39 @@ def get_values(self, item, attribute=None, resolved=True, subgroup=None):
             else :
                 roots = [group]
 
-            for r in roots :
+            for root in roots :
 
                 if item :
-                    nodes = self.get_nodes("entry",{"id" : item} , root=r )
+                    nodes = self.get_nodes("entry",{"id" : item} , root=root )
                 else :
                     # Return all nodes
-                    nodes = self.get_nodes("entry" , root=r)
+                    nodes = self.get_nodes("entry" , root=root)
 
                 # seach in all entry nodes
                 for node in nodes:
 
-                    # Init and construct attribute path
-                    attr      = None
-                    if (r.tag == "job") :
-                        # make job part of attribute path
-                        attr = r.get('name') + "/" + node.get('id')
-                    else:
-                        attr = node.get('id')
-
+                    
                     # Build return structure
-                    g       = group.get('id')
-                    val     = node.get('value')
-                    t       = self._get_type(node)
-                    desc    = self._get_description(node)
-                    default = super(EnvBatch , self)._get_default(node)
-                    filename= self.filename
-
-                    v = { 'group' : g , 'attribute' : attr , 'value' : val , 'type' : t , 'description' : desc , 'default' : default , 'file' : filename}
-                    logger.debug("Found node with value for %s = %s" , item , v )
-                    results.append(v)
+                    attr          = node.get('id')
+                    group_name     = None
+                    
+                    # determine group
+                    if (root.tag == "job") :
+                        group_name = root.get('name') 
+                    else:
+                        group_name = root.get('id')
+
+                    val             = node.get('value')
+                    attribute_type  = self._get_type(node)
+                    desc            = self._get_description(node)
+                    default         = super(EnvBatch , self)._get_default(node)
+                    filename        = self.filename
+
+                    tmp = { 'group' : group_name , 'attribute' : attr , 'value' : val , 'type' : attribute_type , 'description' : desc , 'default' : default , 'file' : filename}
+                    logger.debug("Found node with value for %s = %s" , item , tmp )
+                    
+                    # add single result to list
+                    results.append(tmp) 
 
         logger.debug("(get_values) Return value:  %s" , results )
 
diff --git a/utils/python/CIME/case.py b/utils/python/CIME/case.py
--- a/utils/python/CIME/case.py
+++ b/utils/python/CIME/case.py
@@ -174,7 +174,9 @@ def get_values(self, item=None, attribute=None, resolved=True, subgroup=None):
         """
         Return info object for given item, return all info for all item if item is empty.
         """
-
+        
+        logger.debug("(get_values) Input values: %s , %s , %s , %s , %s" , self.__class__.__name__ , item, attribute, resolved, subgroup)
+        
         # Empty result list
         results = []
 
@@ -199,11 +201,18 @@ def get_values(self, item=None, attribute=None, resolved=True, subgroup=None):
                     for r in result :
                         if type(r['value']) is str:
                             logger.debug("Resolving %s" , r['value'])
-
                             r['value'] = self.get_resolved_value(r['value'])
 
-                results = results + result
-
+                if subgroup :
+                    found = []
+                    for r in result :
+                        if r['group'] == subgroup :
+                            found.append(r)
+                    results += found        
+                else:                 
+                    results = results + result
+                    
+        logger.debug("(get_values) Return value:  %s" , results )            
         return results
 
 


Test patch:
diff --git a/utils/python/tests/scripts_regression_tests b/utils/python/tests/scripts_regression_tests
--- a/utils/python/tests/scripts_regression_tests
+++ b/utils/python/tests/scripts_regression_tests
@@ -915,6 +915,89 @@ class TestSingleSubmit(TestCreateTestCommon):
         self.assertEqual(stat, 0,
                          msg="COMMAND SHOULD HAVE WORKED\nwait_for_tests output:\n%s\n\nerrput:\n%s\n\ncode: %d" % (output, errput, stat))
 
+###############################################################################
+class TestXMLQuery(unittest.TestCase):
+# Testing command line scripts
+###############################################################################
+
+    def setUp(self):
+        # Create case directory
+        self._testroot = MACHINE.get_value("CESMSCRATCHROOT")  # "/tmp/"
+        self._testdirs = []
+        self._do_teardown = []
+
+        testdir = os.path.join(self._testroot, 'scripts_regression_tests.testscripts')
+        machine = 'melvin'
+        if os.path.exists(testdir):
+            shutil.rmtree(testdir)
+        self._testdirs.append(testdir)
+        cmd = "%s/create_newcase --case %s --compset X --res f19_g16 --mach %s " % (SCRIPT_DIR, testdir, machine)
+        stat, output, errput = run_cmd(cmd, ok_to_fail=True, from_dir=SCRIPT_DIR)
+        self.assertEqual(stat, 0, msg="COMMAND '%s' SHOULD HAVE WORKED\noutput:\n%s\n\nerrput:\n%s" % (cmd, output, errput))
+
+        self._do_teardown.append(testdir)
+
+    def tearDown(self):
+        do_teardown = len(self._do_teardown) > 0 and sys.exc_info() == (None, None, None)
+
+        for tfile in self._testdirs:
+            if tfile not in self._do_teardown:
+                print "Detected failed test or user request no teardown"
+                print "Leaving case directory : %s"%tfile
+            elif do_teardown:
+                shutil.rmtree(tfile)
+
+    def test_xmlquery(self):
+        # Set script and script path
+        xmlquery = "./xmlquery"
+        testdir  = self._testdirs[0]
+
+
+        # Check for environment
+        self.assertTrue(os.path.isdir(SCRIPT_DIR))
+        self.assertTrue(os.path.isdir(TOOLS_DIR))
+        self.assertTrue(os.path.isfile(testdir + "/" + xmlquery) )
+
+        # Test command line options
+
+        options = [
+            '' ,
+            '--listall' ,
+            '--listall --valonly' ,
+            "-caseroot " + testdir +" -valonly -subgroup case.run -value JOB_QUEUE" ,
+        ]
+
+        for opt in options :
+
+            cmd = xmlquery + ' ' + opt # .join(opt)
+            output = run_cmd(cmd, from_dir=testdir)
+            self.assertTrue(len(output) , msg="no output for: " + cmd )
+
+    def test_subgroup(self):
+        # Set script and script path
+        xmlquery = "./xmlquery"
+        testdir  = self._testdirs[0]
+
+        options = [
+            '-caseroot ' + testdir + ' -valonly -value JOB_QUEUE'  ,
+            '-caseroot ' + testdir + ' -valonly -subgroup case.run -value JOB_QUEUE' ,
+         ]
+
+        # Get value and group information
+        base_out = ''
+        cmd     = xmlquery + " " + options[0]
+        base_out = run_cmd(cmd, from_dir=testdir)
+
+        group_out = ''
+        cmd      = xmlquery + " " + options[1]
+        group_out = run_cmd(cmd, from_dir=testdir)
+
+        searchObj = re.search( r'(.*)(case.run:JOB_QUEUE)\t*(.*)', base_out)
+
+        # Test group option
+        self.assertTrue(len(base_out) , msg="no output for " + cmd)
+        self.assertEqual(searchObj.group() , group_out)
+
 ###############################################################################
 
 # Machinery for Macros generation tests.