diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 1180a5fce9a..495bd88573e 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -153,7 +153,7 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - name: Cache inputdata - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: /storage/inputdata key: inputdata-2 diff --git a/CIME/XML/env_postprocessing.py b/CIME/XML/env_postprocessing.py new file mode 100644 index 00000000000..90f56f24d64 --- /dev/null +++ b/CIME/XML/env_postprocessing.py @@ -0,0 +1,22 @@ +""" +Interface to the env_postprocessing.xml file. This class inherits from EnvBase +""" +from CIME.XML.standard_module_setup import * + +from CIME.XML.env_base import EnvBase + +from CIME import utils + +logger = logging.getLogger(__name__) + + +class EnvPostprocessing(EnvBase): + def __init__( + self, case_root=None, infile="env_postprocessing.xml", read_only=False + ): + """ + initialize an object interface to file env_postprocessing.xml in the case directory + """ + schema = os.path.join(utils.get_schema_path(), "env_entry_id.xsd") + + EnvBase.__init__(self, case_root, infile, schema=schema, read_only=read_only) diff --git a/CIME/XML/postprocessing.py b/CIME/XML/postprocessing.py new file mode 100644 index 00000000000..3287d145142 --- /dev/null +++ b/CIME/XML/postprocessing.py @@ -0,0 +1,40 @@ +""" +Interface to the config_postprocessing.xml file. This class inherits from EntryID +""" + +from CIME.XML.standard_module_setup import * +from CIME.XML.entry_id import EntryID +from CIME.XML.files import Files +from CIME.utils import expect + +logger = logging.getLogger(__name__) + + +class Postprocessing(EntryID): + def __init__(self, infile=None, files=None): + """ + initialize an object + """ + if files is None: + files = Files() + if infile is None: + infile = files.get_value("POSTPROCESSING_SPEC_FILE") + if infile is not None: + self.file_exists = os.path.isfile(infile) + else: + self.file_exists = False + if not self.file_exists: + return + expect(infile, "No postprocessing file defined in {}".format(files.filename)) + + schema = files.get_schema("POSTPROCESSING_SPEC_FILE") + + EntryID.__init__(self, infile, schema=schema) + + # Append the contents of $HOME/.cime/config_postprocessing.xml if it exists + # This could cause problems if node matchs are repeated when only one is expected + infile = os.path.join( + os.environ.get("HOME"), ".cime", "config_postprocessing.xml" + ) + if os.path.exists(infile): + EntryID.read(self, infile) diff --git a/CIME/case/case.py b/CIME/case/case.py index 4e2677c81fe..8ec0708198b 100644 --- a/CIME/case/case.py +++ b/CIME/case/case.py @@ -29,6 +29,7 @@ from CIME.XML.grids import Grids from CIME.XML.batch import Batch from CIME.XML.workflow import Workflow +from CIME.XML.postprocessing import Postprocessing from CIME.XML.pio import PIO from CIME.XML.archive import Archive from CIME.XML.env_test import EnvTest @@ -40,6 +41,7 @@ from CIME.XML.env_archive import EnvArchive from CIME.XML.env_batch import EnvBatch from CIME.XML.env_workflow import EnvWorkflow +from CIME.XML.env_postprocessing import EnvPostprocessing from CIME.XML.generic_xml import GenericXML from CIME.user_mod_support import apply_user_mods from CIME.aprun import get_aprun_cmd_for_case @@ -109,6 +111,7 @@ def __init__(self, case_root=None, read_only=True, record=False, non_local=False case_root ), ) + self._existing_case = os.path.isdir(case_root) self._caseroot = case_root logger.debug("Initializing Case.") @@ -356,6 +359,10 @@ def read_xml(self): self._env_entryid_files.append( EnvWorkflow(self._caseroot, read_only=self._force_read_only) ) + if not self._existing_case or os.path.isfile("env_postprocessing.xml"): + self._env_entryid_files.append( + EnvPostprocessing(self._caseroot, read_only=self._force_read_only) + ) if os.path.isfile(os.path.join(self._caseroot, "env_test.xml")): self._env_entryid_files.append( @@ -430,6 +437,19 @@ def flush(self, flushall=False): # do not flush if caseroot wasnt created return + _postprocessing_spec_file = self.get_value("POSTPROCESSING_SPEC_FILE") + if _postprocessing_spec_file is not None: + have_postprocessing = os.path.isfile(_postprocessing_spec_file) + else: + have_postprocessing = False + if not have_postprocessing: + # Remove env_postprocessing.xml from self._files + self._files = [ + file + for file in self._files + if file.get_id() != "env_postprocessing.xml" + ] + for env_file in self._files: env_file.write(force_write=flushall) @@ -1577,6 +1597,11 @@ def configure( workflow = Workflow(files=files) + postprocessing = Postprocessing(files=files) + if postprocessing.file_exists: + env_postprocessing = self.get_env("postprocessing") + env_postprocessing.add_elements_by_group(srcobj=postprocessing) + env_batch.set_batch_system(batch, batch_system_type=batch_system_type) bjobs = workflow.get_workflow_jobs(machine=machine_name, workflowid=workflowid) @@ -2216,6 +2241,8 @@ def set_file(self, xmlfile): new_env_file = EnvBatch(infile=xmlfile) elif ftype == "env_workflow.xml": new_env_file = EnvWorkflow(infile=xmlfile) + elif ftype == "env_postprocessing.xml": + new_env_file = EnvPostprocessing(infile=xmlfile) elif ftype == "env_test.xml": new_env_file = EnvTest(infile=xmlfile) elif ftype == "env_archive.xml": diff --git a/CIME/data/config/cesm/config_files.xml b/CIME/data/config/cesm/config_files.xml index ba7d3aaa240..3cc9eac40b2 100644 --- a/CIME/data/config/cesm/config_files.xml +++ b/CIME/data/config/cesm/config_files.xml @@ -55,6 +55,15 @@ $CIMEROOT/CIME/data/config/xml_schemas/config_batch.xsd + + char + $SRCROOT/tools/CUPiD/cime_config/config_tool.xml + case_last + env_case.xml + file containing postprocessing XML configuration (for documentation only - DO NOT EDIT) + $CIMEROOT/CIME/data/config/xml_schemas/entry_id.xsd + + char $SRCROOT/ccs_config/machines/config_workflow.xml diff --git a/CIME/data/config/config_headers.xml b/CIME/data/config/config_headers.xml index c0d939cf3a4..10f59f2c770 100644 --- a/CIME/data/config/config_headers.xml +++ b/CIME/data/config/config_headers.xml @@ -17,6 +17,13 @@ + +
+ These variables may be changed anytime during a run, they + control jobs that are dependent on case.run. +
+
+
These variables CANNOT BE CHANGED once a case has been created.