From 235e0bf346677ed46f21eefcc1d3bf47ef9aa506 Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Wed, 18 Dec 2024 09:41:32 -0700 Subject: [PATCH] Bugfix #2830 develop fix missing log output (#2841) * Per #2830, skip closing of log handlers for METplusConfig objects that are created for copying values for process list instances so they are not closed before the end of the run. * remove some output directories after tests are run --- internal/tests/pytests/util/run_util/test_run_util.py | 10 ++++++++++ metplus/util/config_metplus.py | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/internal/tests/pytests/util/run_util/test_run_util.py b/internal/tests/pytests/util/run_util/test_run_util.py index 9b95e891e..62d9e8149 100644 --- a/internal/tests/pytests/util/run_util/test_run_util.py +++ b/internal/tests/pytests/util/run_util/test_run_util.py @@ -51,6 +51,10 @@ 'INPUT_THRESH', ] +def remove_output_base(config): + config_output_base = config.getdir("OUTPUT_BASE") + if config_output_base and os.path.exists(config_output_base): + ru.shutil.rmtree(config_output_base) def get_run_util_configs(conf_name): script_dir = os.path.dirname(__file__) @@ -130,6 +134,7 @@ def test_pre_run_setup(): expected_stage = os.path.join(actual.get('config', 'OUTPUT_BASE'), 'stage') assert actual.get('config', 'STAGING_DIR') == expected_stage assert actual.get('user_env_vars', 'GODS_OF_WEATHER') == 'Indra_Thor_Zeus' + remove_output_base(actual) @pytest.mark.util @@ -139,6 +144,7 @@ def test_pre_run_setup_env_vars(): actual = ru.pre_run_setup(conf_inputs) assert actual.env['MY_ENV_VAR'] == '42' assert actual.get('config', 'OMP_NUM_THREADS') == '4' + remove_output_base(actual) @pytest.mark.util @@ -262,6 +268,7 @@ def test_run_metplus(capfd, config_dict, expected, check_err): else: assert err == '' + remove_output_base(config) @pytest.mark.parametrize( "side_effect,return_value,check_err", @@ -285,6 +292,8 @@ def test_run_metplus_errors(capfd, side_effect, return_value, check_err): else: assert err == check_err + remove_output_base(config) + @pytest.mark.util def test_get_wrapper_instance(metplus_config): @@ -308,6 +317,7 @@ def test_get_wrapper_instance_raises(capfd, side_effect, check_err): assert actual == None out, err = capfd.readouterr() assert check_err in err + remove_output_base(config) @pytest.mark.util diff --git a/metplus/util/config_metplus.py b/metplus/util/config_metplus.py index 238b2c10b..bbfd010a6 100644 --- a/metplus/util/config_metplus.py +++ b/metplus/util/config_metplus.py @@ -462,6 +462,8 @@ def __init__(self, conf=None, run_id=None): super().__init__(conf) self._cycle = None self.run_id = run_id if run_id else str(uuid.uuid4())[0:8] + # if run ID is specified, this is a copy of a config + self.is_copy = run_id is not None self._logger = logging.getLogger(f'metplus.{self.run_id}') # config.logger is called in wrappers, so set this name # so the code doesn't break @@ -475,6 +477,9 @@ def __init__(self, conf=None, run_id=None): def __del__(self): """!When object is deleted, close and remove all log handlers""" + # do not close log handlers if this is a copied config object + if self.is_copy: + return handlers = self.logger.handlers[:] for handler in handlers: self.logger.removeHandler(handler)