Skip to content

Commit

Permalink
Merge pull request #4366 from ESMCI/fixes_record_cmd
Browse files Browse the repository at this point in the history
This PR fixes restoring quotes to command arguments that have been
recorded by replay.sh. The original quotes around these arguments
are stripped by the invoking shell and python is unable to pass these
through to sys.argv.

Test suite: scripts_regression_tests.py
Test baseline: n/a
Test namelist changes: n/a
Test status: n/a

Fixes #4361
User interface changes?: n/a
Update gh-pages html (Y/N)?: N
  • Loading branch information
jasonb5 authored Feb 28, 2023
2 parents aa83ca0 + 4d5d926 commit 9333a6f
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 1 deletion.
33 changes: 32 additions & 1 deletion CIME/case/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -2255,7 +2255,7 @@ def record_cmd(self, cmd=None, init=False):
cimeroot = self.get_value("CIMEROOT")

if cmd is None:
cmd = list(sys.argv)
cmd = self.fix_sys_argv_quotes(list(sys.argv))

if init:
ctime = time.strftime("%Y-%m-%d %H:%M:%S")
Expand Down Expand Up @@ -2294,6 +2294,37 @@ def record_cmd(self, cmd=None, init=False):
except PermissionError:
logger.warning("Could not write to 'replay.sh' script")

def fix_sys_argv_quotes(self, cmd):
"""Fixes removed quotes from argument list.
Restores quotes to `--val` and `KEY=VALUE` from sys.argv.
"""
# handle fixing quotes
# case 1: "--val", " -nlev 276 "
# case 2: "-val" , " -nlev 276 "
# case 3: CAM_CONFIG_OPTS=" -nlev 276 "
for i, item in enumerate(cmd):
if re.match("[-]{1,2}val", item) is not None:
if i + 1 >= len(cmd):
continue

# only quote if value contains spaces
if " " in cmd[i + 1]:
cmd[i + 1] = f'"{cmd[i + 1]}"'
else:
m = re.search("([^=]*)=(.*)", item)

if m is None:
continue

g = m.groups()

# only quote if value contains spaces
if " " in g[1]:
cmd[i] = f'{g[0]}="{g[1]}"'

return cmd

def create(
self,
casename,
Expand Down
69 changes: 69 additions & 0 deletions CIME/tests/test_unit_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,75 @@ def setUp(self):
self.srcroot = os.path.abspath(cime_utils.get_src_root())
self.tempdir = tempfile.TemporaryDirectory()

@mock.patch("CIME.case.case.Case.read_xml")
def test_fix_sys_argv_quotes(self, read_xml):
input_data = ["./xmlquery", "--val", "PIO"]
expected_data = ["./xmlquery", "--val", "PIO"]

with tempfile.TemporaryDirectory() as tempdir:
make_valid_case(tempdir)

with Case(tempdir) as case:
output_data = case.fix_sys_argv_quotes(input_data)

assert output_data == expected_data

@mock.patch("CIME.case.case.Case.read_xml")
def test_fix_sys_argv_quotes_incomplete(self, read_xml):
input_data = ["./xmlquery", "--val"]
expected_data = ["./xmlquery", "--val"]

with tempfile.TemporaryDirectory() as tempdir:
make_valid_case(tempdir)

with Case(tempdir) as case:
output_data = case.fix_sys_argv_quotes(input_data)

assert output_data == expected_data

@mock.patch("CIME.case.case.Case.read_xml")
def test_fix_sys_argv_quotes_val(self, read_xml):
input_data = ["./xmlquery", "--val", "-test"]
expected_data = ["./xmlquery", "--val", "-test"]

with tempfile.TemporaryDirectory() as tempdir:
make_valid_case(tempdir)

with Case(tempdir) as case:
output_data = case.fix_sys_argv_quotes(input_data)

assert output_data == expected_data

@mock.patch("CIME.case.case.Case.read_xml")
def test_fix_sys_argv_quotes_val_quoted(self, read_xml):
input_data = ["./xmlquery", "--val", " -nlev 267 "]
expected_data = ["./xmlquery", "--val", '" -nlev 267 "']

with tempfile.TemporaryDirectory() as tempdir:
make_valid_case(tempdir)

with Case(tempdir) as case:
output_data = case.fix_sys_argv_quotes(input_data)

assert output_data == expected_data

@mock.patch("CIME.case.case.Case.read_xml")
def test_fix_sys_argv_quotes_kv(self, read_xml):
input_data = ["./xmlquery", "CAM_CONFIG_OPTS= -nlev 267", "OTHER_OPTS=-test"]
expected_data = [
"./xmlquery",
'CAM_CONFIG_OPTS=" -nlev 267"',
"OTHER_OPTS=-test",
]

with tempfile.TemporaryDirectory() as tempdir:
make_valid_case(tempdir)

with Case(tempdir) as case:
output_data = case.fix_sys_argv_quotes(input_data)

assert output_data == expected_data

@mock.patch("CIME.case.case.Case.read_xml")
@mock.patch("sys.argv", ["/src/create_newcase", "--machine", "docker"])
@mock.patch("time.strftime", return_value="00:00:00")
Expand Down

0 comments on commit 9333a6f

Please sign in to comment.