-
Notifications
You must be signed in to change notification settings - Fork 216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow user_mods directory in compset definition #1366
Merged
Merged
Changes from 8 commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
09ed442
New method for setting and detecting pause alarms in component models
b5dc7b7
Make sure ESP runs on pause for PRE test. Add missing units to driver…
40a4333
Fixed pylint issue with unused output from cprnc
1a1b475
Remove unused variable, modify initialization to clarify purpose.
1d39746
Fixed pylint issue
8b2a76d
Remove conditional pio1 code
jayeshkrishna 314a93c
Make Machines.get_value more likely to return values of the correct type
jgfouca cb1ffe8
Inform user of machine
jgfouca ad0a5c1
Big cs.status upgrade
jgfouca 562cf4b
add support for user_mods in compset definition
jedwards4b efb7125
fix pylint issue
jedwards4b ea4a759
fix no-match args
jedwards4b 685c3fe
first changes needed for aquaplanet som
9cc7740
Fix precedence of user_mods application
billsacks 8664933
fixed issue with using new user_mods element in compset definition
01ad744
Add unit tests for user_mod_support
billsacks 0a38bb5
Force user to always go through case.submit
jgfouca 8e8fd62
fix typo
billsacks ec95467
Fix timing of applying compset user_mods
billsacks 9903472
Merge pull request #1350 from gold2718/pausePOP
jedwards4b 1335a62
Merge pull request #1357 from ESMCI/jayeshkrishna/rem_cond_pio1_code
jedwards4b 2530c66
Merge pull request #1360 from ESMCI/jgfouca/machine_get_value_type
jedwards4b 8282a8f
Merge pull request #1361 from ESMCI/jgfouca/inform_user_of_machine
jedwards4b dd5a30b
Merge pull request #1362 from ESMCI/jgfouca/force_resubmit_to_use_submit
jedwards4b d0e277d
Merge pull request #1363 from ESMCI/jgfouca/big_cs_status_upgrade
jedwards4b 8075121
add comment to README and stdout
jedwards4b 29e0159
add support for user_mods in compset definition
jedwards4b 8c2bd51
fix pylint issue
jedwards4b a1656f4
fix no-match args
jedwards4b 582e308
first changes needed for aquaplanet som
28e84b7
Fix precedence of user_mods application
billsacks 4df9f7e
fixed issue with using new user_mods element in compset definition
4f6bb99
Add unit tests for user_mod_support
billsacks fc4ac0b
fix typo
billsacks 50e5d7a
Fix timing of applying compset user_mods
billsacks 3075576
add comment to README and stdout
jedwards4b 0266e9d
Print user_mods directory upfront
billsacks ddd2162
Merge branch 'mvertens/usermods_in_compset' of github.com:ESMCI/cime …
jedwards4b File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
#!/usr/bin/env python | ||
|
||
import unittest | ||
import shutil | ||
import tempfile | ||
import os | ||
from CIME.user_mod_support import apply_user_mods | ||
|
||
# ======================================================================== | ||
# Define some parameters | ||
# ======================================================================== | ||
|
||
_SOURCEMODS = os.path.join("SourceMods", "src.drv") | ||
|
||
class TestUserModSupport(unittest.TestCase): | ||
|
||
# ======================================================================== | ||
# Test helper functions | ||
# ======================================================================== | ||
|
||
def setUp(self): | ||
self._caseroot = tempfile.mkdtemp() | ||
self._caseroot_sourcemods = os.path.join(self._caseroot, _SOURCEMODS) | ||
os.makedirs(self._caseroot_sourcemods) | ||
self._user_mods_parent_dir = tempfile.mkdtemp() | ||
|
||
def tearDown(self): | ||
shutil.rmtree(self._caseroot, ignore_errors=True) | ||
shutil.rmtree(self._user_mods_parent_dir, ignore_errors=True) | ||
|
||
def createUserMod(self, name, include_dirs=None): | ||
"""Create a user_mods directory with the given name. | ||
|
||
This directory is created within self._user_mods_parent_dir | ||
|
||
For name='foo', it will contain: | ||
|
||
- A user_nl_cpl file with contents: | ||
foo | ||
|
||
- A shell_commands file with contents: | ||
echo foo >> /PATH/TO/CASEROOT/shell_commands_result | ||
|
||
- A file in _SOURCEMODS named myfile.F90 with contents: | ||
foo | ||
|
||
If include_dirs is given, it should be a list of strings, giving names | ||
of other user_mods directories to include. e.g., if include_dirs is | ||
['foo1', 'foo2'], then this will create a file 'include_user_mods' that | ||
contains paths to the 'foo1' and 'foo2' user_mods directories, one per | ||
line. | ||
""" | ||
|
||
mod_dir = os.path.join(self._user_mods_parent_dir, name) | ||
os.makedirs(mod_dir) | ||
mod_dir_sourcemods = os.path.join(mod_dir, _SOURCEMODS) | ||
os.makedirs(mod_dir_sourcemods) | ||
|
||
with open(os.path.join(mod_dir, "user_nl_cpl"), "w") as user_nl_cpl: | ||
user_nl_cpl.write(name + "\n") | ||
with open(os.path.join(mod_dir, "shell_commands"), "w") as shell_commands: | ||
command = "echo %s >> %s/shell_commands_result\n"%(name, | ||
self._caseroot) | ||
shell_commands.write(command) | ||
with open(os.path.join(mod_dir_sourcemods, "myfile.F90"), "w") as f90_file: | ||
f90_file.write(name + "\n") | ||
|
||
if include_dirs: | ||
with open(os.path.join(mod_dir, "include_user_mods"), "w") as include_user_mods: | ||
for one_include in include_dirs: | ||
include_user_mods.write(os.path.join(self._user_mods_parent_dir, one_include) + "\n") | ||
|
||
def assertResults(self, expected_user_nl_cpl, | ||
expected_shell_commands_result, | ||
expected_sourcemod, | ||
msg = ""): | ||
"""Asserts that the contents of the files in self._caseroot match expectations | ||
|
||
If msg is provided, it is printed for some failing assertions | ||
""" | ||
|
||
path_to_user_nl_cpl = os.path.join(self._caseroot, "user_nl_cpl") | ||
self.assertTrue(os.path.isfile(path_to_user_nl_cpl), | ||
msg = msg + ": user_nl_cpl does not exist") | ||
with open(path_to_user_nl_cpl, "r") as user_nl_cpl: | ||
contents = user_nl_cpl.read() | ||
self.assertEqual(expected_user_nl_cpl, contents) | ||
|
||
path_to_shell_commands_result = os.path.join(self._caseroot, "shell_commands_result") | ||
self.assertTrue(os.path.isfile(path_to_shell_commands_result), | ||
msg = msg + ": shell_commands_result does not exist") | ||
with open(path_to_shell_commands_result, "r") as shell_commands_result: | ||
contents = shell_commands_result.read() | ||
self.assertEqual(expected_shell_commands_result, contents) | ||
|
||
path_to_sourcemod = os.path.join(self._caseroot_sourcemods, "myfile.F90") | ||
self.assertTrue(os.path.isfile(path_to_sourcemod), | ||
msg = msg + ": sourcemod file does not exist") | ||
with open(path_to_sourcemod, "r") as sourcemod: | ||
contents = sourcemod.read() | ||
self.assertEqual(expected_sourcemod, contents) | ||
|
||
# ======================================================================== | ||
# Begin actual tests | ||
# ======================================================================== | ||
|
||
def test_basic(self): | ||
self.createUserMod("foo") | ||
apply_user_mods(self._caseroot, | ||
os.path.join(self._user_mods_parent_dir, "foo")) | ||
self.assertResults(expected_user_nl_cpl = "foo\n", | ||
expected_shell_commands_result = "foo\n", | ||
expected_sourcemod = "foo\n", | ||
msg = "test_basic") | ||
|
||
def test_two_applications(self): | ||
"""If apply_user_mods is called twice, the second should appear after the first so that it takes precedence.""" | ||
|
||
self.createUserMod("foo1") | ||
self.createUserMod("foo2") | ||
apply_user_mods(self._caseroot, | ||
os.path.join(self._user_mods_parent_dir, "foo1")) | ||
apply_user_mods(self._caseroot, | ||
os.path.join(self._user_mods_parent_dir, "foo2")) | ||
self.assertResults(expected_user_nl_cpl = "foo1\nfoo2\n", | ||
expected_shell_commands_result = "foo1\nfoo2\n", | ||
expected_sourcemod = "foo2\n", | ||
msg = "test_two_applications") | ||
|
||
def test_include(self): | ||
"""If there is an included mod, the main one should appear after the included one so that it takes precedence.""" | ||
|
||
self.createUserMod("base") | ||
self.createUserMod("derived", include_dirs=["base"]) | ||
|
||
apply_user_mods(self._caseroot, | ||
os.path.join(self._user_mods_parent_dir, "derived")) | ||
|
||
self.assertResults(expected_user_nl_cpl = "base\nderived\n", | ||
expected_shell_commands_result = "base\nderived\n", | ||
expected_sourcemod = "derived\n", | ||
msg = "test_include") | ||
|
||
def test_duplicate_includes(self): | ||
"""Test multiple includes, where both include the same base mod. | ||
|
||
The base mod should only be included once. | ||
""" | ||
|
||
self.createUserMod("base") | ||
self.createUserMod("derived1", include_dirs=["base"]) | ||
self.createUserMod("derived2", include_dirs=["base"]) | ||
self.createUserMod("derived_combo", | ||
include_dirs = ["derived1", "derived2"]) | ||
|
||
apply_user_mods(self._caseroot, | ||
os.path.join(self._user_mods_parent_dir, "derived_combo")) | ||
|
||
# NOTE(wjs, 2017-04-15) The ordering of derived1 vs. derived2 is not | ||
# critical here: If this aspect of the behavior changes, the | ||
# expected_contents can be changed to match the new behavior in this | ||
# respect. | ||
expected_contents = """base | ||
derived2 | ||
derived1 | ||
derived_combo | ||
""" | ||
self.assertResults(expected_user_nl_cpl = expected_contents, | ||
expected_shell_commands_result = expected_contents, | ||
expected_sourcemod = "derived_combo\n", | ||
msg = "test_duplicate_includes") |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason that get_resolved_value is done here, at the last minute, rather than being done when this element is first retrieved from the xml file? It seems like the latter would be less error-prone as the code evolves. But I don't know what the standard convention is in this respect.