249 lines
7.5 KiB
Python
Executable File
249 lines
7.5 KiB
Python
Executable File
#!/usr/bin/env python2.7
|
|
import unittest
|
|
import nml
|
|
|
|
def version(vn):
|
|
# Converts module version string to int tuple as PEP-440
|
|
return tuple(map(int, vn.split(".")))
|
|
|
|
HEADER = """
|
|
!! =====================================
|
|
!! An example FORTRAN 90 namelist
|
|
!! =====================================
|
|
&namex
|
|
"""
|
|
NOHEADER = "&namex\n"
|
|
LOGIC = " ln_test = .TRUE. ! Comment\n"
|
|
NUMERIC = " nn_off_idx = 1 2 3\n"
|
|
NOSPACE = " nn_off_idx=1 2 3\n"
|
|
NEGATIVE = " nn_off_idx = -1 -2 -3\n"
|
|
LIST = " off_files = 'a.nc' 'b.nc' 'c.nc' ! Comment\n"
|
|
STRING = ' contact = "example@nowhere.com" ! Comment\n'
|
|
COMMENT = ' ! x = y '
|
|
FOOTER = "/\n"
|
|
NOFOOTER = "/"
|
|
|
|
class TestNamelist(unittest.TestCase):
|
|
def setUp(self):
|
|
self.logic_text = "\n".join([HEADER, LOGIC, FOOTER])
|
|
self.numeric_text = "\n".join([HEADER, NUMERIC, FOOTER])
|
|
self.nospace_text = "\n".join([HEADER, NOSPACE, FOOTER])
|
|
self.neg_numeric_text = "\n".join([HEADER, NEGATIVE, FOOTER])
|
|
self.list_text = "\n".join([HEADER, LIST, FOOTER])
|
|
self.mix_text = "\n".join([HEADER, LIST, NUMERIC, FOOTER])
|
|
self.string_text = "\n".join([HEADER, STRING, FOOTER])
|
|
self.comment_text = "\n".join([HEADER, COMMENT, FOOTER])
|
|
self.no_trail_text = "\n".join([HEADER, NUMERIC, LIST, NOFOOTER])
|
|
|
|
def test_should_handle_footer(self):
|
|
data = nml.variables(self.no_trail_text)
|
|
truth = {"nn_off_idx": "1 2 3",
|
|
"off_files": "'a.nc' 'b.nc' 'c.nc'"}
|
|
self.assertDictEqual(data, truth)
|
|
|
|
def test_mix_data(self):
|
|
data = nml.variables(self.mix_text)
|
|
truth = {"nn_off_idx": "1 2 3",
|
|
"off_files": "'a.nc' 'b.nc' 'c.nc'"}
|
|
self.assertDictEqual(data, truth)
|
|
|
|
def test_comment_data(self):
|
|
data = nml.variables(self.comment_text)
|
|
truth = {}
|
|
self.assertDictEqual(data, truth)
|
|
|
|
def test_logical_data(self):
|
|
data = nml.variables(self.logic_text)
|
|
truth = {"ln_test": ".TRUE."}
|
|
self.assertDictEqual(data, truth)
|
|
|
|
def test_numeric_data(self):
|
|
data = nml.variables(self.numeric_text)
|
|
truth = {"nn_off_idx": "1 2 3"}
|
|
self.assertDictEqual(data, truth)
|
|
|
|
def test_nospace_data(self):
|
|
data = nml.variables(self.nospace_text)
|
|
truth = {"nn_off_idx": "1 2 3"}
|
|
self.assertDictEqual(data, truth)
|
|
|
|
def test_negative_numeric_data(self):
|
|
data = nml.variables(self.neg_numeric_text)
|
|
truth = {"nn_off_idx": "-1 -2 -3"}
|
|
self.assertDictEqual(data, truth)
|
|
|
|
def test_string_data(self):
|
|
data = nml.variables(self.string_text)
|
|
truth = {"contact": '"example@nowhere.com"'}
|
|
self.assertDictEqual(data, truth)
|
|
|
|
def test_list_data(self):
|
|
data = nml.variables(self.list_text)
|
|
truth = {"off_files": "'a.nc' 'b.nc' 'c.nc'"}
|
|
self.assertDictEqual(data, truth)
|
|
|
|
def test_replace_variable_comment(self):
|
|
FIXTURE = " x = 'y' ! comment \n"
|
|
RESULT = " x = 'z' ! comment \n"
|
|
text = nml.replace(FIXTURE, {"x": "z"})
|
|
self.assertEqual(text, RESULT)
|
|
|
|
def test_replace_variable_no_comment(self):
|
|
FIXTURE = " x = 'y' \n"
|
|
RESULT = " x = 'z' \n"
|
|
text = nml.replace(FIXTURE, {"x": "z"})
|
|
self.assertEqual(text, RESULT)
|
|
|
|
def test_replace_variable_no_space(self):
|
|
FIXTURE = " x='y' \n"
|
|
RESULT = " x='z' \n"
|
|
text = nml.replace(FIXTURE, {"x": "z"})
|
|
self.assertEqual(text, RESULT)
|
|
|
|
def test_replace_variable_no_space_comment(self):
|
|
FIXTURE = " x='y' ! comment \n"
|
|
RESULT = " x='z' ! comment \n"
|
|
text = nml.replace(FIXTURE, {"x": "z"})
|
|
self.assertEqual(text, RESULT)
|
|
|
|
@unittest.skipIf(version(nml.__version__) < (1, 0),
|
|
"Not implemented in this version")
|
|
def test_multiline_variable_replace(self):
|
|
# As a result of a code review
|
|
FIXTURE = " x = 1, \n 2"
|
|
RESULT = " x = 3, \n 4"
|
|
text = nml.replace(FIXTURE, {"x": [3,4]})
|
|
self.assertEqual(text, RESULT)
|
|
|
|
class TestCombinedNamelists(unittest.TestCase):
|
|
def setUp(self):
|
|
self.minimal = """&namone
|
|
/"""
|
|
self.blanks = """
|
|
&namone
|
|
/
|
|
&namtwo
|
|
/
|
|
"""
|
|
self.contents = """
|
|
&namone
|
|
Content 1
|
|
/
|
|
&namtwo
|
|
Content 2
|
|
/
|
|
"""
|
|
self.contents_slash = """
|
|
&namone
|
|
Content 1 ! Y/N
|
|
/
|
|
&namtwo
|
|
Content 2
|
|
/
|
|
"""
|
|
def test_should_select_name_from_minimal_namelist(self):
|
|
data = nml.namelists(self.minimal)
|
|
result = {"namone": "&namone\n/"}
|
|
self.assertDictEqual(data, result)
|
|
|
|
def test_should_select_names(self):
|
|
data = nml.namelists(self.blanks)
|
|
result = {"namone": "&namone\n/",
|
|
"namtwo": "&namtwo\n/"}
|
|
self.assertDictEqual(data, result)
|
|
|
|
def test_should_select_contents(self):
|
|
data = nml.namelists(self.contents)
|
|
result = {"namone": "&namone\nContent 1\n/",
|
|
"namtwo": "&namtwo\nContent 2\n/"}
|
|
self.assertDictEqual(data, result)
|
|
|
|
def test_should_select_contents_with_forward_slash(self):
|
|
data = nml.namelists(self.contents_slash)
|
|
result = {"namone": "&namone\nContent 1 ! Y/N\n/",
|
|
"namtwo": "&namtwo\nContent 2\n/"}
|
|
self.assertDictEqual(data, result)
|
|
|
|
|
|
class TestToString(unittest.TestCase):
|
|
def setUp(self):
|
|
self.char_list = ["a.nc", "b.nc", "c.nc"]
|
|
self.num_list = [1, 3, 7]
|
|
self.char = "foo@bar.com"
|
|
self.num = 10
|
|
self.mixed_list = ["foo.nc", -1, True]
|
|
self.mixed_str_list = map(nml.quote, ["foo.nc", "-1", ".TRUE."])
|
|
|
|
def test_should_format_mixed_list(self):
|
|
data = nml.tostring(self.mixed_list)
|
|
result = "'foo.nc', -1, .TRUE."
|
|
self.assertEqual(data, result)
|
|
|
|
def test_should_format_numeric_list(self):
|
|
data = nml.tostring(self.num_list)
|
|
result = "1 3 7"
|
|
self.assertEqual(data, result)
|
|
|
|
def test_should_format_character_list(self):
|
|
data = nml.tostring(self.char_list)
|
|
result = "'a.nc', 'b.nc', 'c.nc'"
|
|
self.assertEqual(data, result)
|
|
|
|
def test_should_format_strings(self):
|
|
data = nml.tostring(self.char)
|
|
result = "'%s'" % (self.char,)
|
|
self.assertEqual(data, result)
|
|
|
|
def test_should_format_numbers(self):
|
|
data = nml.tostring(self.num)
|
|
result = str(self.num)
|
|
self.assertEqual(data, result)
|
|
|
|
def test_should_not_format_numeric_string(self):
|
|
input = "3.14159"
|
|
self.assertEqual(nml.tostring(input), input)
|
|
|
|
def test_should_format_logicals(self):
|
|
data = nml.tostring(True)
|
|
result = ".TRUE."
|
|
self.assertEqual(data.upper(), result)
|
|
|
|
def test_should_not_format_string_of_list_data(self):
|
|
for input in ["1 2 3", "1, 2, 3", ".TRUE. .FALSE."]:
|
|
case = nml.tostring(input)
|
|
self.assertEqual(case, input)
|
|
|
|
def test_should_treat_mixed_numeric_character_data_as_character(self):
|
|
case = nml.tostring(self.mixed_str_list)
|
|
result = "'foo.nc', '-1', '.TRUE.'"
|
|
self.assertEqual(case, result)
|
|
|
|
class TestUpdateNamelist(unittest.TestCase):
|
|
def setUp(self):
|
|
self.empty = """
|
|
&namone
|
|
/
|
|
"""
|
|
self.single = """
|
|
&namone
|
|
x = 'y'
|
|
/
|
|
"""
|
|
self.single_update = """
|
|
&namone
|
|
x = 'z'
|
|
/
|
|
"""
|
|
|
|
def test_should_append_new_variable_to_namelist(self):
|
|
trial = nml.update("namone", self.empty, {"x": "'y'"})
|
|
self.assertEqual(trial, self.single)
|
|
|
|
def test_should_update_existing_variables(self):
|
|
trial = nml.update("namone", self.single, {"x": "'z'"})
|
|
self.assertEqual(trial, self.single_update)
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|
|
|