diff --git a/ush/python/pygw/src/pygw/logger.py b/ush/python/pygw/src/pygw/logger.py index 15b0e74c72..30d0210665 100644 --- a/ush/python/pygw/src/pygw/logger.py +++ b/ush/python/pygw/src/pygw/logger.py @@ -3,6 +3,7 @@ """ import sys +from functools import wraps from pathlib import Path from typing import Union, List import logging @@ -222,3 +223,47 @@ def add_file_handler(cls, logfile_path: Union[str, Path], handler.setFormatter(logging.Formatter(_format)) return handler + + +def logit(logger, name=None, message=None): + """ + Add logging to a function. + Parameters + ---------- + logger : Logger + Logger object + name : str + Name of the module to be logged + default: __module__ + message : str + Name of the function to be logged + default: __name__ + """ + + def decorate(func): + + log_name = name if name else func.__module__ + log_msg = message if message else log_name + "." + func.__name__ + + @wraps(func) + def wrapper(*args, **kwargs): + + passed_args = [repr(aa) for aa in args] + passed_kwargs = [f"{kk}={repr(vv)}" for kk, vv in list(kwargs.items())] + call_msg = 'BEGIN: ' + log_msg + f"( {', '.join(passed_args + passed_kwargs)} )" + + # Begin the logging with printing input arguments + logger.debug(call_msg) + + # Call the function + retval = func(*args, **kwargs) + + # Close the logging with printing the return val + ret_msg = ' END: ' + log_msg + f" returning {retval}" + logger.debug(ret_msg) + + return retval + + return wrapper + + return decorate diff --git a/ush/python/pygw/src/pygw/yaml_file.py b/ush/python/pygw/src/pygw/yaml_file.py index 5803271105..327a7ca1eb 100644 --- a/ush/python/pygw/src/pygw/yaml_file.py +++ b/ush/python/pygw/src/pygw/yaml_file.py @@ -17,14 +17,17 @@ class YAMLFile(AttrDict): def __init__(self, path=None, data=None): super().__init__() + if path and data: - print("Ignoring 'data' and using 'path' argument") # TODO: use logging - if path: + print("Ignoring 'data' and using 'path' argument") + + config = None + if path is not None: config = parse_yaml(path=path) - elif data: + elif data is not None: config = parse_yaml(data=data) - if config: + if config is not None: self.update(config) def save(self, target): diff --git a/ush/python/pygw/src/tests/test_logger.py b/ush/python/pygw/src/tests/test_logger.py index 2cce0f7449..a9b4504d57 100644 --- a/ush/python/pygw/src/tests/test_logger.py +++ b/ush/python/pygw/src/tests/test_logger.py @@ -1,4 +1,5 @@ from pygw.logger import Logger +from pygw.logger import logit level = 'debug' number_of_log_msgs = 5 @@ -40,3 +41,27 @@ def test_logger(tmp_path): lev = line.split('-')[3].strip().lower() message = line.split(':')[-1].strip() assert reference[lev] == message + + +def test_logit(tmp_path): + + logger = Logger('test_logit', level=level, colored_log=True) + + @logit(logger) + def add(x, y): + return x + y + + @logit(logger) + def usedict(n, j=0, k=1): + return n + j + k + + @logit(logger, 'example') + def spam(): + print('Spam!') + + add(2, 3) + usedict(2, 3) + usedict(2, k=3) + spam() + + assert True diff --git a/ush/python/pygw/src/tests/test_yaml_file.py b/ush/python/pygw/src/tests/test_yaml_file.py new file mode 100644 index 0000000000..276eb2c548 --- /dev/null +++ b/ush/python/pygw/src/tests/test_yaml_file.py @@ -0,0 +1,74 @@ +import os +from pygw.yaml_file import YAMLFile + +host_yaml = """ +host: + hostname: test_host + host_user: !ENV ${USER} +""" + +conf_yaml = """ +config: + config_file: !ENV ${TMP_PATH}/config.yaml + user: !ENV ${USER} + host_file: !INC ${TMP_PATH}/host.yaml +""" + +tmpl_yaml = """ +config: + config_file: !ENV ${TMP_PATH}/config.yaml + user: !ENV ${USER} + host_file: !INC ${TMP_PATH}/host.yaml +tmpl: + cdate: '{{PDY}}{{cyc}}' + homedir: $(user) +""" +# Note the quotes ' ' around {{ }}. These quotes are necessary otherwise YAMLFile will fail parsing + + +def test_yaml_file(tmp_path): + + # Create temporary yaml files w/ tags + config_file_path = tmp_path / 'config.yaml' + with open(config_file_path, 'w') as conf_file: + conf_file.write(conf_yaml) + + with open(tmp_path / 'host.yaml', 'w') as host_file: + host_file.write(host_yaml) + + # Set env. variable + os.environ['TMP_PATH'] = str(tmp_path) + conf = YAMLFile(path=config_file_path) + + # Write out yaml file + yaml_out = tmp_path / 'output.yaml' + conf.save(yaml_out) + + # Read in the yaml file and compare w/ conf + yaml_in = YAMLFile(path=str(yaml_out)) + + assert yaml_in == conf + + +def test_yaml_file_with_templates(tmp_path): + + # Create temporary yaml files w/ tags + tmpl_file_path = tmp_path / 'tmpl.yaml' + with open(tmpl_file_path, 'w') as tmpl_file: + tmpl_file.write(tmpl_yaml) + + with open(tmp_path / 'host.yaml', 'w') as host_file: + host_file.write(host_yaml) + + # Set env. variable + os.environ['TMP_PATH'] = str(tmp_path) + conf = YAMLFile(path=tmpl_file_path) + + # Write out yaml file + yaml_out = tmp_path / 'tmpl_output.yaml' + conf.save(yaml_out) + + # Read in the yaml file and compare w/ conf + yaml_in = YAMLFile(path=yaml_out) + + assert yaml_in == conf