Skip to content

Commit

Permalink
Implement new functionality needed in user_nl_utils
Browse files Browse the repository at this point in the history
And remove old, no-longer-needed functionality

Test suite: None
Test baseline: N/A
Test namelist changes: N/A
Test status: N/A

Fixes: None

User interface changes?: No

Code review: None
  • Loading branch information
billsacks committed Aug 7, 2016
1 parent bf416c5 commit 8660a9c
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 249 deletions.
3 changes: 1 addition & 2 deletions utils/python/CIME/SystemTests/lii.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from CIME.SystemTests.system_tests_compare_two_clone import SystemTestsCompareTwoClone
from CIME.XML.standard_module_setup import *
from CIME.SystemTests.test_utils.user_nl_utils import save_user_nl_files, append_to_saved_files
from CIME.SystemTests.test_utils.user_nl_utils import append_to_user_nl_files

logger = logging.getLogger(__name__)

Expand All @@ -29,7 +29,6 @@ def _common_setup(self):
self._case.set_value("HIST_N","$STOP_N")

def _case_one_setup(self):
# FIXME(wjs, 2016-08-05) Need to implement this method
append_to_user_nl_files(caseroot = self._get_caseroot(),
component = "clm",
contents = "use_init_interp = .false.")
Expand Down
168 changes: 17 additions & 151 deletions utils/python/CIME/SystemTests/test_utils/tests/test_user_nl_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,109 +49,6 @@ def assertFileContentsEqual(self, expected, filepath, msg=None):
# Begin actual tests
# ========================================================================

def test_save(self):
# Define some variables
component = 'foo'
save_dirname = 'saved_files'
orig_contents = 'bar = 42\n'

# Setup
filename = self.write_user_nl_file(component, orig_contents)

# Exercise
user_nl_utils.save_user_nl_files(caseroot = self._caseroot,
component = component,
save_dirname = save_dirname)

# Verify
self.assertTrue(os.path.isfile(
os.path.join(self._caseroot, save_dirname, filename)),
msg = 'copied file should exist in save directory')

def test_save_multiple_files(self):
# Define some variables
component = 'foo'
save_dirname = 'saved_files'
orig_contents1 = 'bar = 42\n'
orig_contents2 = 'bar = 17\n'

# Setup
filename1 = self.write_user_nl_file(component, orig_contents1, suffix='_0001')
filename2 = self.write_user_nl_file(component, orig_contents2, suffix='_0002')

# Exercise
user_nl_utils.save_user_nl_files(caseroot = self._caseroot,
component = component,
save_dirname = save_dirname)

# Verify
self.assertTrue(os.path.isfile(
os.path.join(self._caseroot, save_dirname, filename1)),
msg = 'copied file 1 should exist in save directory')
self.assertTrue(os.path.isfile(
os.path.join(self._caseroot, save_dirname, filename2)),
msg = 'copied file 2 should exist in save directory')


def test_save_with_existing_directory(self):
# It should be okay to call save with an existing directory.

# Define some variables
component = 'foo'
save_dirname = 'saved_files'
orig_contents = 'bar = 42\n'

# Setup
filename = self.write_user_nl_file(component, orig_contents)
os.makedirs(os.path.join(self._caseroot, save_dirname))

# Exercise
user_nl_utils.save_user_nl_files(caseroot = self._caseroot,
component = component,
save_dirname = save_dirname)

# Verify
self.assertTrue(os.path.isfile(
os.path.join(self._caseroot, save_dirname, filename)),
msg = 'copied file should exist in save directory')

def test_save_twice_should_not_overwrite_existing_files(self):
# If you call save_user_nl_files when there are already saved user_nl
# files in the save directory, then they should not be overwritten

# Define some variables
component = 'foo'
save_dirname = 'saved_files'
orig_contents = 'bar = 42\n'
new_contents = 'bar = 17\n'

# Setup
filename = self.write_user_nl_file(component, orig_contents)
# do an initial copy to the save directory to set things up for the real
# test:
user_nl_utils.save_user_nl_files(caseroot = self._caseroot,
component = component,
save_dirname = save_dirname)
# now overwrite the file in the case directory:
filename = self.write_user_nl_file(component, new_contents)

# Exercise
user_nl_utils.save_user_nl_files(caseroot = self._caseroot,
component = component,
save_dirname = save_dirname)

# Verify
self.assertFileContentsEqual(orig_contents,
os.path.join(self._caseroot, save_dirname, filename))

def test_save_with_no_file_raises_exception(self):
# Exercise & verify
self.assertRaisesRegexp(RuntimeError, "No user_nl files found",
user_nl_utils.save_user_nl_files,
caseroot = self._caseroot,
component = 'foo')


def test_append(self):
# Define some variables
component = 'foo'
Expand All @@ -162,88 +59,57 @@ def test_append(self):

# Setup
filename = self.write_user_nl_file(component, orig_contents)
user_nl_utils.save_user_nl_files(caseroot = self._caseroot,
component = component)

# Exercise
user_nl_utils.append_to_saved_files(caseroot = self._caseroot,
component = component,
contents = contents_to_append)
user_nl_utils.append_to_user_nl_files(caseroot = self._caseroot,
component = component,
contents = contents_to_append)

# Verify
expected_contents = orig_contents + '\n' + contents_to_append + '\n'
self.assertFileContentsEqual(expected_contents,
os.path.join(self._caseroot, filename))


def test_two_appends(self):
# If you call append twice, only the second append should be present in
# the final file.
#
# This test also tests appending with multi-instance

# Define some variables
def test_append_multiple_files(self):
# Simulates a multi-instance test
component = 'foo'
orig_contents1 = 'bar = 42'
orig_contents2 = 'bar = 17'
contents_to_append_first = 'baz = 101'
contents_to_append_second = 'baz = 201'
contents_to_append = 'baz = 101'

# Setup
filename1 = self.write_user_nl_file(component, orig_contents1, suffix='_0001')
filename2 = self.write_user_nl_file(component, orig_contents2, suffix='_0002')
user_nl_utils.save_user_nl_files(caseroot = self._caseroot,
component = component)

# First append should not affect final result
user_nl_utils.append_to_saved_files(caseroot = self._caseroot,
component = component,
contents = contents_to_append_first)

# Exercise
user_nl_utils.append_to_saved_files(caseroot = self._caseroot,
component = component,
contents = contents_to_append_second)
user_nl_utils.append_to_user_nl_files(caseroot = self._caseroot,
component = component,
contents = contents_to_append)

# Verify
expected_contents1 = orig_contents1 + '\n' + contents_to_append_second + '\n'
expected_contents2 = orig_contents2 + '\n' + contents_to_append_second + '\n'
expected_contents1 = orig_contents1 + '\n' + contents_to_append + '\n'
expected_contents2 = orig_contents2 + '\n' + contents_to_append + '\n'
self.assertFileContentsEqual(expected_contents1,
os.path.join(self._caseroot, filename1))
self.assertFileContentsEqual(expected_contents2,
os.path.join(self._caseroot, filename2))

def test_append_without_savedir_raises_exception(self):
# This test verifies that you get an exception if you try to call
# append_to_saved_files without first calling save_user_nl_files

# Exercise and verify
self.assertRaisesRegexp(RuntimeError, "No user_nl files found",
user_nl_utils.append_to_saved_files,
caseroot = self._caseroot,
component = 'foo',
contents = 'bar')

def test_append_without_saved_files_raises_exception(self):
def test_append_without_files_raises_exception(self):
# This test verifies that you get an exception if you call
# append_to_saved_files using a save directory that does not contain the
# user_nl files of interest
# append_to_user_nl_files when there are no user_nl files of interest

# Define some variables
component_saved = 'foo'
component_exists = 'foo'
component_for_append = 'bar'

# Setup
# Create files in caseroot for both component_saved and component_for_append...
filename = self.write_user_nl_file(component_saved, 'irrelevant contents')
filename = self.write_user_nl_file(component_for_append, 'other irrelevant contents')
# ... but only call save on component_saved
user_nl_utils.save_user_nl_files(caseroot = self._caseroot,
component = component_saved)
# Create file in caseroot for component_exists, but not for component_for_append
filename = self.write_user_nl_file(component_exists, 'irrelevant contents')

# Exercise & verify
self.assertRaisesRegexp(RuntimeError, "No user_nl files found",
user_nl_utils.append_to_saved_files,
user_nl_utils.append_to_user_nl_files,
caseroot = self._caseroot,
component = component_for_append,
contents = 'irrelevant contents to append')
Expand Down
113 changes: 17 additions & 96 deletions utils/python/CIME/SystemTests/test_utils/user_nl_utils.py
Original file line number Diff line number Diff line change
@@ -1,131 +1,52 @@
"""
This module contains functions for working with user_nl files in system tests.
Typical usage for a test that needs to tweak a component's user_nl files for
each of multiple runs is:
In the pre-build phase:
user_nl_utils.save_user_nl_files(caseroot, component)
Then, in the initial setup for each run:
user_nl_utils.append_to_saved_files(caseroot, component, contents)
"""

import shutil
import os
import glob

_DEFAULT_SAVE_DIRNAME = "saved_user_nl_files"

def save_user_nl_files(caseroot, component,
save_dirname = _DEFAULT_SAVE_DIRNAME):
"""
Save original user_nl files so that these originals can be restored later.
If copies already exist in the given save directory, they will NOT be
overwritten. Thus, it is safe to call this multiple times with the same
arguments: only the first call will have an effect. (However, this behavior
means that, in the unlikely event that user_nl files were present in the
given save directory before the first call to save_user_nl_files - such as
due to a poorly-chosen save_dirname - then these original files will be kept
in place, which is likely not what you want.)
Arguments:
casedir: (string) Full path to the case directory
component: (string) name of component (e.g., 'clm'). This is used to determine
which user_nl files are copied and later modified. For example, for
component='clm', this object will operate on all user_nl files matching
the pattern 'user_nl_clm*'. (We do a wildcard match to handle
multi-instance tests.)
save_dirname: (string) name of directory to be created within the case directory,
containing saved copies of the relevant user_nl file(s)
def append_to_user_nl_files(caseroot, component, contents):
"""

save_fullpath = os.path.join(caseroot, save_dirname)

if not os.path.exists(save_fullpath):
os.makedirs(save_fullpath)

files = _get_list_of_user_nl_files(caseroot, component)

if len(files) == 0:
raise RuntimeError('No user_nl files found for component ' + component)

for one_file in files:
orig_file = os.path.join(caseroot, one_file)
saved_file = os.path.join(save_fullpath, one_file)
if not os.path.exists(saved_file):
shutil.copy(orig_file, saved_file)

def append_to_saved_files(caseroot, component, contents,
save_dirname = _DEFAULT_SAVE_DIRNAME):
"""
Copy the saved files back to the case directory, then append the
string given by 'contents' to the end of each of the saved
user_nl files for the given component (there may be multiple such user_nl files in
the case of a multi-instance test).
Append the string given by 'contents' to the end of each user_nl file for
the given component (there may be multiple such user_nl files in the case of
a multi-instance test).
Also puts new lines before and after the appended text - so 'contents'
does not need to contain a trailing new line (but it's also okay if it
does).
Because this method starts with the saved version of the files (from the
call to save_user_nl_files), you can NOT use this twice to append
additional text: the second call will overwrite the contents added in
the first call.
This should be called after save_user_nl_files has been called with the same
caseroot, component and save_dirname arguments.
Args:
caseroot (str): Full path to the case directory
Arguments:
component (str): Name of component (e.g., 'clm'). This is used to
determine which user_nl files are appended to. For example, for
component='clm', this function will operate on all user_nl files
matching the pattern 'user_nl_clm*'. (We do a wildcard match to
handle multi-instance tests.)
casedir: (string) Full path to the case directory
component: (string) name of component (e.g., 'clm'). This is used to determine
which user_nl files are copied and later modified. For example, for
component='clm', this object will operate on all user_nl files matching
the pattern 'user_nl_clm*'. (We do a wildcard match to handle
multi-instance tests.)
contents: (string) contents to append to the end of each user_nl file
save_dirname: (string) name of sub-directory within the case directory that
contains saved copies of the relevant user_nl file(s)
contents (str): Contents to append to the end of each user_nl file
"""

save_fullpath = os.path.join(caseroot, save_dirname)

files = _get_list_of_user_nl_files(save_fullpath, component)
files = _get_list_of_user_nl_files(caseroot, component)

if len(files) == 0:
raise RuntimeError('No user_nl files found for component ' + component
+ ' in ' + save_fullpath)
raise RuntimeError('No user_nl files found for component ' + component)

for one_file in files:
saved_file = os.path.join(save_fullpath, one_file)
new_file = os.path.join(caseroot, one_file)
shutil.copy(saved_file, new_file)
with open(new_file, 'a') as user_nl_file:
with open(one_file, 'a') as user_nl_file:
user_nl_file.write('\n' + contents + '\n')


def _get_list_of_user_nl_files(path, component):
"""Get a list of all user_nl files in the current path for the component
of interest. For a component 'foo', we match all files of the form
user_nl_foo* - with a wildcard match at the end in order to match files
in a multi-instance case.
The list of returned files gives just the file names themselves (i.e.,
the basenames).
The list of returned files gives their full path.
"""

file_pattern = 'user_nl_' + component + '*'
file_list = glob.glob(os.path.join(path, file_pattern))
file_basename_list = [os.path.basename(one_file) for one_file in file_list]

return file_basename_list
return file_list

0 comments on commit 8660a9c

Please sign in to comment.