prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  cs.status reset to force rebuild
  I would like an additional option to cs.status or perhaps create_test that
  would reset all cases in a test suite to the PEND SHAREDLIB_BUILD state so that 
  all tests are rebuilt before being restarted. 
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `CIME/cs_status.py`
  Content:
  ```
  1 """
  2 Implementation of the cs.status script, which prints the status of all
  3 of the tests in one or more test suites
  4 """
  5 
  6 from __future__ import print_function
  7 from CIME.XML.standard_module_setup import *
  8 from CIME.XML.expected_fails_file import ExpectedFailsFile
  9 from CIME.test_status import TestStatus
  10 import os
  11 import sys
  12 from collections import defaultdict
  13 
  14 
  15 def cs_status(
  16     test_paths,
  17     summary=False,
  18     fails_only=False,
  19     count_fails_phase_list=None,
  20     check_throughput=False,
  21     check_memory=False,
  22     expected_fails_filepath=None,
  23     out=sys.stdout,
  24 ):
  25     """Print the test statuses of all tests in test_paths. The default
  26     is to print to stdout, but this can be overridden with the 'out'
  27     argument.
  28 
  29     If summary is True, then only the overall status of each test is printed
  30 
  31     If fails_only is True, then only test failures are printed (this
  32     includes PENDs as well as FAILs).
  33 
  34     If count_fails_phase_list is provided, it should be a list of phases
  35     (from the phases given by test_status.ALL_PHASES). For each phase in
  36     this list: do not give line-by-line output; instead, just report the
  37     total number of tests that have not PASSed this phase (this includes
  38     PENDs and FAILs). (This is typically used with the fails_only
  39     option, but it can also be used without that option.)
  40 
  41     If expected_fails_filepath is provided, it should be a string giving
  42     the full path to a file listing expected failures for this test
  43     suite. Expected failures are then labeled as such in the output.
  44     """
  45     expect(not (summary and fails_only), "Cannot have both summary and fails_only")
  46     expect(
  47         not (summary and count_fails_phase_list),
  48         "Cannot have both summary and count_fails_phase_list",
  49     )
  50     if count_fails_phase_list is None:
  51         count_fails_phase_list = []
  52     non_pass_counts = dict.fromkeys(count_fails_phase_list, 0)
  53     xfails = _get_xfails(expected_fails_filepath)
  54     test_id_output = defaultdict(str)
  55     test_id_counts = defaultdict(int)
  56     for test_path in test_paths:
  57         test_dir = os.path.dirname(test_path)
  58         ts = TestStatus(test_dir=test_dir)
  59         test_id = os.path.basename(test_dir).split(".")[-1]
  60         if summary:
  61             output = _overall_output(
  62                 ts, "  {status} {test_name}\n", check_throughput, check_memory
  63             )
  64         else:
  65             if fails_only:
  66                 output = ""
  67             else:
  68                 output = _overall_output(
  69                     ts,
  70                     "  {test_name} (Overall: {status}) details:\n",
  71                     check_throughput,
  72                     check_memory,
  73                 )
  74             output += ts.phase_statuses_dump(
  75                 prefix="    ",
  76                 skip_passes=fails_only,
  77                 skip_phase_list=count_fails_phase_list,
  78                 xfails=xfails.get(ts.get_name()),
  79             )
  80             if count_fails_phase_list:
  81                 ts.increment_non_pass_counts(non_pass_counts)
  82 
  83         test_id_output[test_id] += output
  84         test_id_counts[test_id] += 1
  85 
  86     for test_id in sorted(test_id_output):
  87         count = test_id_counts[test_id]
  88         print(
  89             "{}: {} test{}".format(test_id, count, "s" if count > 1 else ""), file=out
  90         )
  91         print(test_id_output[test_id], file=out)
  92         print(" ", file=out)
  93 
  94     if count_fails_phase_list:
  95         print(72 * "=", file=out)
  96         print("Non-PASS results for select phases:", file=out)
  97         for phase in count_fails_phase_list:
  98             print("{} non-passes: {}".format(phase, non_pass_counts[phase]), file=out)
  99 
  100 
  101 def _get_xfails(expected_fails_filepath):
  102     """Returns a dictionary of ExpectedFails objects, where the keys are test names
  103 
  104     expected_fails_filepath should be either a string giving the path to
  105     the file containing expected failures, or None. If None, then this
  106     returns an empty dictionary (as if expected_fails_filepath were
  107     pointing to a file with no expected failures listed).
  108     """
  109     if expected_fails_filepath is not None:
  110         expected_fails_file = ExpectedFailsFile(expected_fails_filepath)
  111         xfails = expected_fails_file.get_expected_fails()
  112     else:
  113         xfails = {}
  114     return xfails
  115 
  116 
  117 def _overall_output(ts, format_str, check_throughput, check_memory):
  118     """Returns a string giving the overall test status
  119 
  120     Args:
  121     ts: TestStatus object
  122     format_str (string): string giving the format of the output; must
  123         contain place-holders for status and test_name
  124     """
  125     test_name = ts.get_name()
  126     status = ts.get_overall_test_status(
  127         check_throughput=check_throughput,
  128         check_memory=check_memory,
  129     )[0]
  130     return format_str.format(status=status, test_name=test_name)
  131
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/CIME/cs_status.py b/CIME/cs_status.py
  --- a/CIME/cs_status.py
  +++ b/CIME/cs_status.py
  @@ -6,7 +6,7 @@
   from __future__ import print_function
   from CIME.XML.standard_module_setup import *
   from CIME.XML.expected_fails_file import ExpectedFailsFile
  -from CIME.test_status import TestStatus
  +from CIME.test_status import TestStatus, SHAREDLIB_BUILD_PHASE, TEST_PEND_STATUS
   import os
   import sys
   from collections import defaultdict
  @@ -20,6 +20,7 @@
       check_throughput=False,
       check_memory=False,
       expected_fails_filepath=None,
  +    force_rebuild=False,
       out=sys.stdout,
   ):
       """Print the test statuses of all tests in test_paths. The default
  @@ -56,6 +57,11 @@
       for test_path in test_paths:
           test_dir = os.path.dirname(test_path)
           ts = TestStatus(test_dir=test_dir)
  +
  +        if force_rebuild:
  +            with ts:
  +                ts.set_status(SHAREDLIB_BUILD_PHASE, TEST_PEND_STATUS)
  +
           test_id = os.path.basename(test_dir).split(".")[-1]
           if summary:
               output = _overall_output(
  
verification_info: {"golden_diff": "diff --git a/CIME/cs_status.py b/CIME/cs_status.py\n--- a/CIME/cs_status.py\n+++ b/CIME/cs_status.py\n@@ -6,7 +6,7 @@\n from __future__ import print_function\n from CIME.XML.standard_module_setup import *\n from CIME.XML.expected_fails_file import ExpectedFailsFile\n-from CIME.test_status import TestStatus\n+from CIME.test_status import TestStatus, SHAREDLIB_BUILD_PHASE, TEST_PEND_STATUS\n import os\n import sys\n from collections import defaultdict\n@@ -20,6 +20,7 @@\n     check_throughput=False,\n     check_memory=False,\n     expected_fails_filepath=None,\n+    force_rebuild=False,\n     out=sys.stdout,\n ):\n     \"\"\"Print the test statuses of all tests in test_paths. The default\n@@ -56,6 +57,11 @@\n     for test_path in test_paths:\n         test_dir = os.path.dirname(test_path)\n         ts = TestStatus(test_dir=test_dir)\n+\n+        if force_rebuild:\n+            with ts:\n+                ts.set_status(SHAREDLIB_BUILD_PHASE, TEST_PEND_STATUS)\n+\n         test_id = os.path.basename(test_dir).split(\".\")[-1]\n         if summary:\n             output = _overall_output(\n", "issue": "cs.status reset to force rebuild\nI would like an additional option to cs.status or perhaps create_test that\r\nwould reset all cases in a test suite to the PEND SHAREDLIB_BUILD state so that \r\nall tests are rebuilt before being restarted. \n", "before_files": [{"content": "\"\"\"\nImplementation of the cs.status script, which prints the status of all\nof the tests in one or more test suites\n\"\"\"\n\nfrom __future__ import print_function\nfrom CIME.XML.standard_module_setup import *\nfrom CIME.XML.expected_fails_file import ExpectedFailsFile\nfrom CIME.test_status import TestStatus\nimport os\nimport sys\nfrom collections import defaultdict\n\n\ndef cs_status(\n    test_paths,\n    summary=False,\n    fails_only=False,\n    count_fails_phase_list=None,\n    check_throughput=False,\n    check_memory=False,\n    expected_fails_filepath=None,\n    out=sys.stdout,\n):\n    \"\"\"Print the test statuses of all tests in test_paths. The default\n    is to print to stdout, but this can be overridden with the 'out'\n    argument.\n\n    If summary is True, then only the overall status of each test is printed\n\n    If fails_only is True, then only test failures are printed (this\n    includes PENDs as well as FAILs).\n\n    If count_fails_phase_list is provided, it should be a list of phases\n    (from the phases given by test_status.ALL_PHASES). For each phase in\n    this list: do not give line-by-line output; instead, just report the\n    total number of tests that have not PASSed this phase (this includes\n    PENDs and FAILs). (This is typically used with the fails_only\n    option, but it can also be used without that option.)\n\n    If expected_fails_filepath is provided, it should be a string giving\n    the full path to a file listing expected failures for this test\n    suite. Expected failures are then labeled as such in the output.\n    \"\"\"\n    expect(not (summary and fails_only), \"Cannot have both summary and fails_only\")\n    expect(\n        not (summary and count_fails_phase_list),\n        \"Cannot have both summary and count_fails_phase_list\",\n    )\n    if count_fails_phase_list is None:\n        count_fails_phase_list = []\n    non_pass_counts = dict.fromkeys(count_fails_phase_list, 0)\n    xfails = _get_xfails(expected_fails_filepath)\n    test_id_output = defaultdict(str)\n    test_id_counts = defaultdict(int)\n    for test_path in test_paths:\n        test_dir = os.path.dirname(test_path)\n        ts = TestStatus(test_dir=test_dir)\n        test_id = os.path.basename(test_dir).split(\".\")[-1]\n        if summary:\n            output = _overall_output(\n                ts, \"  {status} {test_name}\\n\", check_throughput, check_memory\n            )\n        else:\n            if fails_only:\n                output = \"\"\n            else:\n                output = _overall_output(\n                    ts,\n                    \"  {test_name} (Overall: {status}) details:\\n\",\n                    check_throughput,\n                    check_memory,\n                )\n            output += ts.phase_statuses_dump(\n                prefix=\"    \",\n                skip_passes=fails_only,\n                skip_phase_list=count_fails_phase_list,\n                xfails=xfails.get(ts.get_name()),\n            )\n            if count_fails_phase_list:\n                ts.increment_non_pass_counts(non_pass_counts)\n\n        test_id_output[test_id] += output\n        test_id_counts[test_id] += 1\n\n    for test_id in sorted(test_id_output):\n        count = test_id_counts[test_id]\n        print(\n            \"{}: {} test{}\".format(test_id, count, \"s\" if count > 1 else \"\"), file=out\n        )\n        print(test_id_output[test_id], file=out)\n        print(\" \", file=out)\n\n    if count_fails_phase_list:\n        print(72 * \"=\", file=out)\n        print(\"Non-PASS results for select phases:\", file=out)\n        for phase in count_fails_phase_list:\n            print(\"{} non-passes: {}\".format(phase, non_pass_counts[phase]), file=out)\n\n\ndef _get_xfails(expected_fails_filepath):\n    \"\"\"Returns a dictionary of ExpectedFails objects, where the keys are test names\n\n    expected_fails_filepath should be either a string giving the path to\n    the file containing expected failures, or None. If None, then this\n    returns an empty dictionary (as if expected_fails_filepath were\n    pointing to a file with no expected failures listed).\n    \"\"\"\n    if expected_fails_filepath is not None:\n        expected_fails_file = ExpectedFailsFile(expected_fails_filepath)\n        xfails = expected_fails_file.get_expected_fails()\n    else:\n        xfails = {}\n    return xfails\n\n\ndef _overall_output(ts, format_str, check_throughput, check_memory):\n    \"\"\"Returns a string giving the overall test status\n\n    Args:\n    ts: TestStatus object\n    format_str (string): string giving the format of the output; must\n        contain place-holders for status and test_name\n    \"\"\"\n    test_name = ts.get_name()\n    status = ts.get_overall_test_status(\n        check_throughput=check_throughput,\n        check_memory=check_memory,\n    )[0]\n    return format_str.format(status=status, test_name=test_name)\n", "path": "CIME/cs_status.py"}], "after_files": [{"content": "\"\"\"\nImplementation of the cs.status script, which prints the status of all\nof the tests in one or more test suites\n\"\"\"\n\nfrom __future__ import print_function\nfrom CIME.XML.standard_module_setup import *\nfrom CIME.XML.expected_fails_file import ExpectedFailsFile\nfrom CIME.test_status import TestStatus, SHAREDLIB_BUILD_PHASE, TEST_PEND_STATUS\nimport os\nimport sys\nfrom collections import defaultdict\n\n\ndef cs_status(\n    test_paths,\n    summary=False,\n    fails_only=False,\n    count_fails_phase_list=None,\n    check_throughput=False,\n    check_memory=False,\n    expected_fails_filepath=None,\n    force_rebuild=False,\n    out=sys.stdout,\n):\n    \"\"\"Print the test statuses of all tests in test_paths. The default\n    is to print to stdout, but this can be overridden with the 'out'\n    argument.\n\n    If summary is True, then only the overall status of each test is printed\n\n    If fails_only is True, then only test failures are printed (this\n    includes PENDs as well as FAILs).\n\n    If count_fails_phase_list is provided, it should be a list of phases\n    (from the phases given by test_status.ALL_PHASES). For each phase in\n    this list: do not give line-by-line output; instead, just report the\n    total number of tests that have not PASSed this phase (this includes\n    PENDs and FAILs). (This is typically used with the fails_only\n    option, but it can also be used without that option.)\n\n    If expected_fails_filepath is provided, it should be a string giving\n    the full path to a file listing expected failures for this test\n    suite. Expected failures are then labeled as such in the output.\n    \"\"\"\n    expect(not (summary and fails_only), \"Cannot have both summary and fails_only\")\n    expect(\n        not (summary and count_fails_phase_list),\n        \"Cannot have both summary and count_fails_phase_list\",\n    )\n    if count_fails_phase_list is None:\n        count_fails_phase_list = []\n    non_pass_counts = dict.fromkeys(count_fails_phase_list, 0)\n    xfails = _get_xfails(expected_fails_filepath)\n    test_id_output = defaultdict(str)\n    test_id_counts = defaultdict(int)\n    for test_path in test_paths:\n        test_dir = os.path.dirname(test_path)\n        ts = TestStatus(test_dir=test_dir)\n\n        if force_rebuild:\n            with ts:\n                ts.set_status(SHAREDLIB_BUILD_PHASE, TEST_PEND_STATUS)\n\n        test_id = os.path.basename(test_dir).split(\".\")[-1]\n        if summary:\n            output = _overall_output(\n                ts, \"  {status} {test_name}\\n\", check_throughput, check_memory\n            )\n        else:\n            if fails_only:\n                output = \"\"\n            else:\n                output = _overall_output(\n                    ts,\n                    \"  {test_name} (Overall: {status}) details:\\n\",\n                    check_throughput,\n                    check_memory,\n                )\n            output += ts.phase_statuses_dump(\n                prefix=\"    \",\n                skip_passes=fails_only,\n                skip_phase_list=count_fails_phase_list,\n                xfails=xfails.get(ts.get_name()),\n            )\n            if count_fails_phase_list:\n                ts.increment_non_pass_counts(non_pass_counts)\n\n        test_id_output[test_id] += output\n        test_id_counts[test_id] += 1\n\n    for test_id in sorted(test_id_output):\n        count = test_id_counts[test_id]\n        print(\n            \"{}: {} test{}\".format(test_id, count, \"s\" if count > 1 else \"\"), file=out\n        )\n        print(test_id_output[test_id], file=out)\n        print(\" \", file=out)\n\n    if count_fails_phase_list:\n        print(72 * \"=\", file=out)\n        print(\"Non-PASS results for select phases:\", file=out)\n        for phase in count_fails_phase_list:\n            print(\"{} non-passes: {}\".format(phase, non_pass_counts[phase]), file=out)\n\n\ndef _get_xfails(expected_fails_filepath):\n    \"\"\"Returns a dictionary of ExpectedFails objects, where the keys are test names\n\n    expected_fails_filepath should be either a string giving the path to\n    the file containing expected failures, or None. If None, then this\n    returns an empty dictionary (as if expected_fails_filepath were\n    pointing to a file with no expected failures listed).\n    \"\"\"\n    if expected_fails_filepath is not None:\n        expected_fails_file = ExpectedFailsFile(expected_fails_filepath)\n        xfails = expected_fails_file.get_expected_fails()\n    else:\n        xfails = {}\n    return xfails\n\n\ndef _overall_output(ts, format_str, check_throughput, check_memory):\n    \"\"\"Returns a string giving the overall test status\n\n    Args:\n    ts: TestStatus object\n    format_str (string): string giving the format of the output; must\n        contain place-holders for status and test_name\n    \"\"\"\n    test_name = ts.get_name()\n    status = ts.get_overall_test_status(\n        check_throughput=check_throughput,\n        check_memory=check_memory,\n    )[0]\n    return format_str.format(status=status, test_name=test_name)\n", "path": "CIME/cs_status.py"}]}