From 27539a8e1b7460a95c4ec538996c115f55a4eeaf Mon Sep 17 00:00:00 2001
From: Karl-Hermann Wieners <karl-hermann.wieners@mpimet.mpg.de>
Date: Fri, 5 Jun 2020 15:00:48 +0000
Subject: [PATCH] mkexp: added 'format_namelist' function allowing to render
 individual groups or full namelists

---
 CHANGES.txt |   6 ++
 mkexp       |  11 ++-
 test.py     | 217 ++++++++++++++++++++++++++--------------------------
 3 files changed, 124 insertions(+), 110 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index 3c57edc..2ec7302 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -16,6 +16,12 @@ Global
   Supports adding, altering, and deleting of keys in arbitrary sections,
   and amendments of header comment
 
+Templates
+---------
+
+* Added 'format_namelist' function allowing to render individual groups,
+  as well as full namelists, identical to the NAMELIST variable
+
 Release 1.0.6
 =============
 
diff --git a/mkexp b/mkexp
index 1c859fc..b90347f 100755
--- a/mkexp
+++ b/mkexp
@@ -150,8 +150,9 @@ def cut_remove_list(section, key):
         del section[key]
     return remove_list
 
-def format_namelist(section):
-    '''Format config section as a namelist'''
+def format_namelist(section, group=None):
+    '''Format config section as a namelist.
+       If given, just format a single namelist group'''
     # Settings
     base_indent = 4
     # Create list of removed namelist groups.
@@ -162,7 +163,8 @@ def format_namelist(section):
                      map(lambda x: re.escape(x.lower()), remove_list))
     # Format namelist groups that were not removed
     lines = StringIO.StringIO()
-    for group, contents in section.iteritems():
+    iterator = {group: section[group]}.iteritems() if group else section.iteritems()
+    for group, contents in iterator:
         if isinstance(contents, dict):
             group_id = group.lower()
             if not any(map(lambda x: re.match(x, group_id), black_list)):
@@ -284,6 +286,9 @@ template_env.globals['context'] = get_context
 template_env.globals['get_dir'] = files.get_dir
 template_env.globals['get_file'] = files.get_file
 
+# - Utility to format namelists or single groups
+template_env.globals['format_namelist'] = format_namelist
+
 # Additional filters
 
 # - A better wordwrap filter
diff --git a/test.py b/test.py
index a1a7f4b..9eee8ad 100644
--- a/test.py
+++ b/test.py
@@ -276,77 +276,6 @@ class ContentTestCase(MkexpSimpleTestCase):
         result = align(result)
         self.assertMultiLineEqual(expected, result)
 
-    def test_namelist_comments(self):
-        exp_id = "test_namelist_comments"
-        job_id = "job"
-        writeconfig(exp_id, """
-            EXP_TYPE =
-            [namelists]
-              [[namelist]]
-                # var_1b = 84
-                [[[group_1]]]
-                  # Comment for var 1a
-                  var_1a = 42 # Inline comment for var 1a
-                # var_2a = 10.5
-                [[[group_2]]]
-                  # Comment for var 2b
-                  var_2b = 21 # Inline comment for var 2b
-            [jobs]
-              [["""+job_id+"""]]
-        """)
-        writetemplate(exp_id, job_id, """
-            %{NAMELIST}
-        """)
-        expected = align("""
-            &group_1
-                ! Comment for var 1a
-                var_1a = 42 ! Inline comment for var 1a
-                ! var_1b = 84
-            /
-            &group_2
-                ! Comment for var 2b
-                var_2b = 21 ! Inline comment for var 2b
-                ! var_2a = 10.5
-            /
-        """)
-        ignore = output(script("mkexp "+exp_id+".config"))
-        result = readfile(join("test", "experiments", exp_id, exp_id+"."+job_id))
-        result = align(result)
-        self.assertMultiLineEqual(expected, result)
-
-    def test_var_in_namelist(self):
-        exp_id = "test_var_in_namelist"
-        job_id = "job"
-        writeconfig(exp_id, """
-            EXP_TYPE =
-            [namelists]
-              [[namelist]]
-                [[[group]]]
-                  var_1 = raw($$value_1)
-                  var_2 = raw($${value_2})
-                  var_3 = a, raw($$value_3), b
-                  var_4 = a$$value_4
-                  var_5 = $${value_5}b
-            [jobs]
-              [["""+job_id+"""]]
-        """)
-        writetemplate(exp_id, job_id, """
-            %{NAMELIST}
-        """)
-        expected = align("""
-            &group
-                var_1 = $value_1
-                var_2 = ${value_2}
-                var_3 = 'a', $value_3, 'b'
-                var_4 = 'a$value_4'
-                var_5 = '${value_5}b'
-            /
-        """)
-        ignore = output(script("mkexp "+exp_id+".config"))
-        result = readfile(join("test", "experiments", exp_id, exp_id+"."+job_id))
-        result = align(result)
-        self.assertMultiLineEqual(expected, result)
-
     def test_split_date(self):
         exp_id = 'test_split_date'
         job_id = 'job'
@@ -440,6 +369,98 @@ class ContentTestCase(MkexpSimpleTestCase):
         result = align(result)
         self.assertMultiLineEqual(expected, result)
 
+    def test_eval(self):
+        self.run_test("""
+            %{VALUE}
+        """, """
+            42
+        """, """
+            VALUE = eval(5*8+2)
+        """)
+
+    def test_eval_time(self):
+        self.run_test("""
+            %{VALUE}
+        """, """
+            1970-01-01
+        """, """
+            VALUE = "eval(time.strftime('%Y-%m-%d', time.gmtime(0)))"
+        """)
+
+    def test_initial_comment_boilerplate(self):
+        writeconfig(self.exp_id, """
+            ######
+            #    #
+            # 42
+            #    #
+            ######
+            EXP_TYPE =
+            [jobs]
+              [["""+self.job_id+"""]]
+        """)
+        writetemplate(self.exp_id, self.job_id, """
+            %{EXP_DESCRIPTION}
+        """)
+        expected = align("""
+            42
+        """)
+        ignore = output(script("mkexp "+self.exp_id+".config"))
+        result = readfile(join("test", "experiments", self.exp_id,
+                               self.exp_id+"."+self.job_id))
+        result = align(result)
+        self.assertMultiLineEqual(expected, result)
+
+class NamelistTestCase(MkexpSimpleTestCase):
+
+    def test_namelist_comments(self):
+        self.run_test("""
+            %{NAMELIST}
+        ""","""
+            &group_1
+                ! Comment for var 1a
+                var_1a = 42 ! Inline comment for var 1a
+                ! var_1b = 84
+            /
+            &group_2
+                ! Comment for var 2b
+                var_2b = 21 ! Inline comment for var 2b
+                ! var_2a = 10.5
+            /
+        ""","""
+            [namelists]
+              [[namelist]]
+                # var_1b = 84
+                [[[group_1]]]
+                  # Comment for var 1a
+                  var_1a = 42 # Inline comment for var 1a
+                # var_2a = 10.5
+                [[[group_2]]]
+                  # Comment for var 2b
+                  var_2b = 21 # Inline comment for var 2b
+        """)
+
+    def test_var_in_namelist(self):
+        self.run_test("""
+            %{NAMELIST}
+        ""","""
+            &group
+                var_1 = $value_1
+                var_2 = ${value_2}
+                var_3 = 'a', $value_3, 'b'
+                var_4 = 'a$value_4'
+                var_5 = '${value_5}b'
+            /
+        ""","""
+            [namelists]
+              [[namelist]]
+                [[[group]]]
+                  var_1 = raw($$value_1)
+                  var_2 = raw($${value_2})
+                  var_3 = a, raw($$value_3), b
+                  var_4 = a$$value_4
+                  var_5 = $${value_5}b
+        """)
+
     def test_namelist_multi_groups(self):
         self.run_test("""
             %{NAMELIST}
@@ -477,46 +498,28 @@ class ContentTestCase(MkexpSimpleTestCase):
                    VALUE = 42
         """)
 
-    def test_eval(self):
+    def test_namelist_format(self):
         self.run_test("""
-            %{VALUE}
+            %{format_namelist(namelists.namelist)}
+            %{format_namelist(namelists.namelist, 'group2')}
         """, """
-            42
-        """, """
-            VALUE = eval(5*8+2)
-        """)
-
-    def test_eval_time(self):
-        self.run_test("""
-            %{VALUE}
-        """, """
-            1970-01-01
+            &group1
+                value = 41
+            /
+            &group2
+                value = 42
+            /
+            &group2
+                value = 42
+            /
         """, """
-            VALUE = "eval(time.strftime('%Y-%m-%d', time.gmtime(0)))"
-        """)
-
-    def test_initial_comment_boilerplate(self):
-        writeconfig(self.exp_id, """
-            ######
-            #    #
-            # 42
-            #    #
-            ######
-            EXP_TYPE =
-            [jobs]
-              [["""+self.job_id+"""]]
-        """)
-        writetemplate(self.exp_id, self.job_id, """
-            %{EXP_DESCRIPTION}
-        """)
-        expected = align("""
-            42
+            [namelists]
+              [[namelist]]
+                [[[group1]]]
+                   value = 41
+                [[[group2]]]
+                   value = 42
         """)
-        ignore = output(script("mkexp "+self.exp_id+".config"))
-        result = readfile(join("test", "experiments", self.exp_id,
-                               self.exp_id+"."+self.job_id))
-        result = align(result)
-        self.assertMultiLineEqual(expected, result)
 
 class JinjaTemplateTestCase(MkexpSimpleTestCase):
 
-- 
GitLab