Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config realize bugfix #525

Merged
merged 13 commits into from
Jul 11, 2024
32 changes: 16 additions & 16 deletions src/uwtools/api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def get_fieldtable_config(
:param stdin_ok: OK to read from ``stdin``?
:return: An initialized ``FieldTableConfig`` object
"""
return _FieldTableConfig(config=_ensure_data_source(config, stdin_ok))
return _FieldTableConfig(config=_ensure_data_source(_str2path(config), stdin_ok))
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved


def get_ini_config(
Expand All @@ -64,7 +64,7 @@ def get_ini_config(
:param stdin_ok: OK to read from ``stdin``?
:return: An initialized ``INIConfig`` object
"""
return _INIConfig(config=_ensure_data_source(config, stdin_ok))
return _INIConfig(config=_ensure_data_source(_str2path(config), stdin_ok))


def get_nml_config(
Expand All @@ -79,7 +79,7 @@ def get_nml_config(
:param stdin_ok: OK to read from ``stdin``?
:return: An initialized ``NMLConfig`` object
"""
return _NMLConfig(config=_ensure_data_source(config, stdin_ok))
return _NMLConfig(config=_ensure_data_source(_str2path(config), stdin_ok))


def get_sh_config(
Expand All @@ -94,7 +94,7 @@ def get_sh_config(
:param stdin_ok: OK to read from ``stdin``?
:return: An initialized ``SHConfig`` object
"""
return _SHConfig(config=_ensure_data_source(config, stdin_ok))
return _SHConfig(config=_ensure_data_source(_str2path(config), stdin_ok))


def get_yaml_config(
Expand All @@ -109,13 +109,13 @@ def get_yaml_config(
:param stdin_ok: OK to read from ``stdin``?
:return: An initialized ``YAMLConfig`` object
"""
return _YAMLConfig(config=_ensure_data_source(config, stdin_ok))
return _YAMLConfig(config=_ensure_data_source(_str2path(config), stdin_ok))


def realize(
input_config: Optional[Union[dict, _Config, Path, str]] = None,
input_config: Optional[Union[_Config, Path, dict, str]] = None,
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved
input_format: Optional[str] = None,
update_config: Optional[Union[dict, _Config, Path, str]] = None,
update_config: Optional[Union[_Config, Path, dict, str]] = None,
update_format: Optional[str] = None,
output_file: Optional[Union[Path, str]] = None,
output_format: Optional[str] = None,
Expand All @@ -124,17 +124,14 @@ def realize(
total: bool = False,
dry_run: bool = False,
stdin_ok: bool = False,
) -> None:
) -> dict:
"""
NB: This docstring is dynamically replaced: See realize.__doc__ definition below.
"""
input_config = (
_YAMLConfig(config=input_config) if isinstance(input_config, dict) else input_config
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved
)
_realize(
input_config=_ensure_data_source(input_config, stdin_ok),
return _realize(
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved
input_config=_ensure_data_source(_str2path(input_config), stdin_ok),
input_format=input_format,
update_config=_ensure_data_source(update_config, stdin_ok),
update_config=_ensure_data_source(_str2path(update_config), stdin_ok),
update_format=update_format,
output_file=_str2path(output_file),
output_format=output_format,
Expand All @@ -150,7 +147,9 @@ def realize_to_dict( # pylint: disable=unused-argument
input_format: Optional[str] = None,
update_config: Optional[Union[dict, _Config, Path, str]] = None,
update_format: Optional[str] = None,
key_path: Optional[list[Union[str, int]]] = None,
values_needed: bool = False,
total: bool = False,
dry_run: bool = False,
stdin_ok: bool = False,
) -> dict:
Expand All @@ -159,7 +158,7 @@ def realize_to_dict( # pylint: disable=unused-argument

See ``realize()`` for details on arguments, etc.
"""
return _realize(**{**locals(), "output_file": Path(os.devnull), "output_format": None})
return realize(**{**locals(), "output_file": Path(os.devnull), "output_format": _FORMAT.yaml})
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved


def validate(
Expand All @@ -179,7 +178,7 @@ def validate(
:return: ``True`` if the YAML file conforms to the schema, ``False`` otherwise
"""
return _validate_yaml(
schema_file=_ensure_data_source(schema_file, stdin_ok), config=_str2path(config)
schema_file=_str2path(schema_file), config=_ensure_data_source(_str2path(config), stdin_ok)
)


Expand Down Expand Up @@ -240,6 +239,7 @@ def validate(
:param total: Require rendering of all Jinja2 variables/expressions
:param dry_run: Log output instead of writing to output
:param stdin_ok: OK to read from ``stdin``?
:return: The ``dict`` representation of the realized config
:raises: UWConfigRealizeError if ``total`` is ``True`` and any Jinja2 variable/expression was not rendered
""".format(
extensions=", ".join(_FORMAT.extensions())
Expand Down
9 changes: 5 additions & 4 deletions src/uwtools/api/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
from uwtools.file import FileCopier as _FileCopier
from uwtools.file import FileLinker as _FileLinker
from uwtools.utils.api import ensure_data_source as _ensure_data_source
from uwtools.utils.api import str2path as _str2path


def copy(
target_dir: Union[Path, str],
config: Optional[Union[dict, Path, str]] = None,
config: Optional[Union[Path, dict, str]] = None,
cycle: Optional[dt.datetime] = None,
leadtime: Optional[dt.timedelta] = None,
keys: Optional[list[str]] = None,
Expand All @@ -34,7 +35,7 @@ def copy(
"""
_FileCopier(
target_dir=Path(target_dir),
config=_ensure_data_source(config, stdin_ok),
config=_ensure_data_source(_str2path(config), stdin_ok),
cycle=cycle,
leadtime=leadtime,
keys=keys,
Expand All @@ -45,7 +46,7 @@ def copy(

def link(
target_dir: Union[Path, str],
config: Optional[Union[dict, Path, str]] = None,
config: Optional[Union[Path, dict, str]] = None,
cycle: Optional[dt.datetime] = None,
leadtime: Optional[dt.timedelta] = None,
keys: Optional[list[str]] = None,
Expand All @@ -66,7 +67,7 @@ def link(
"""
_FileLinker(
target_dir=Path(target_dir),
config=_ensure_data_source(config, stdin_ok),
config=_ensure_data_source(_str2path(config), stdin_ok),
cycle=cycle,
leadtime=leadtime,
keys=keys,
Expand Down
6 changes: 4 additions & 2 deletions src/uwtools/api/rocoto.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ def realize(
:param stdin_ok: OK to read from ``stdin``?
:return: ``True``
"""
_realize(config=_ensure_data_source(config, stdin_ok), output_file=_str2path(output_file))
_realize(
config=_ensure_data_source(_str2path(config), stdin_ok), output_file=_str2path(output_file)
)
return True


Expand All @@ -46,4 +48,4 @@ def validate(
:param stdin_ok: OK to read from ``stdin``?
:return: ``True`` if the XML conforms to the schema, ``False`` otherwise
"""
return _validate(xml_file=_ensure_data_source(xml_file, stdin_ok))
return _validate(xml_file=_ensure_data_source(_str2path(xml_file), stdin_ok))
4 changes: 2 additions & 2 deletions src/uwtools/api/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def render(
result = _render(
values_src=_str2path(values_src),
values_format=values_format,
input_file=_ensure_data_source(input_file, stdin_ok),
input_file=_ensure_data_source(_str2path(input_file), stdin_ok),
output_file=_str2path(output_file),
overrides=overrides,
env=env,
Expand Down Expand Up @@ -104,7 +104,7 @@ def translate(
:return: ``True``
"""
_convert_atparse_to_jinja2(
input_file=_ensure_data_source(input_file, stdin_ok),
input_file=_ensure_data_source(_str2path(input_file), stdin_ok),
output_file=_str2path(output_file),
dry_run=dry_run,
)
Expand Down
35 changes: 17 additions & 18 deletions src/uwtools/config/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ def config_check_depths_update(config_obj: Union[Config, dict], target_format: s


def realize_config(
input_config: Union[Config, Optional[Path]] = None,
input_config: Optional[Union[Config, Path, dict]] = None,
input_format: Optional[str] = None,
update_config: Union[Config, Optional[Path]] = None,
update_config: Optional[Union[Config, Path, dict]] = None,
update_format: Optional[str] = None,
output_file: Optional[Path] = None,
output_format: Optional[str] = None,
Expand All @@ -90,7 +90,7 @@ def realize_config(
"""
NB: This docstring is dynamically replaced: See realize_config.__doc__ definition below.
"""
input_obj, input_format = _realize_config_input_setup(input_config, input_format)
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved
input_obj = _realize_config_input_setup(input_config, input_format)
input_obj = _realize_config_update(input_obj, update_config, update_format)
input_obj.dereference()
output_data, output_format = _realize_config_output_setup(
Expand All @@ -114,7 +114,7 @@ def realize_config(


def _ensure_format(
desc: str, fmt: Optional[str] = None, config: Union[Config, Optional[Path]] = None
desc: str, fmt: Optional[str] = None, config: Optional[Union[Config, Path, dict]] = None
) -> str:
"""
Return the given format, or the appropriate format as deduced from the config.
Expand All @@ -127,11 +127,12 @@ def _ensure_format(
"""
if isinstance(config, Config):
return config.get_format()
if isinstance(config, Path):
return fmt or get_file_format(config)
if isinstance(config, dict):
return fmt or FORMAT.yaml
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved
if fmt is None:
if config is not None:
fmt = get_file_format(config)
else:
raise UWError(f"Either {desc} file format or name must be specified")
raise UWError(f"Either {desc} path or format name must be specified")
return fmt


Expand Down Expand Up @@ -161,24 +162,22 @@ def _print_config_section(config: dict, key_path: list[str]) -> None:


def _realize_config_input_setup(
input_config: Union[Config, Optional[Path]] = None, input_format: Optional[str] = None
) -> tuple[Config, str]:
input_config: Optional[Union[Config, Path, dict]] = None, input_format: Optional[str] = None
) -> Config:
"""
Set up config-realize input.

:param input_config: Input config source (None => read stdin).
:param input_format: Format of the input config.
:return: The input Config object and its format name.
:return: The input Config object.
"""
if isinstance(input_config, Config):
return input_config
input_format = _ensure_format("input", input_format, input_config)
if not input_config:
log.debug("Reading input from stdin")
input_obj: Config = (
input_config
if isinstance(input_config, Config)
else format_to_config(input_format)(config=input_config)
)
return input_obj, input_format
config_obj: Config = format_to_config(input_format)(config=input_config)
return config_obj


def _realize_config_output_setup(
Expand Down Expand Up @@ -209,7 +208,7 @@ def _realize_config_output_setup(

def _realize_config_update(
input_obj: Config,
update_config: Union[Config, Optional[Path]] = None,
update_config: Optional[Union[Config, Path, dict]] = None,
update_format: Optional[str] = None,
) -> Config:
"""
Expand Down
9 changes: 6 additions & 3 deletions src/uwtools/tests/api/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from uwtools.api import config
from uwtools.config.formats.yaml import YAMLConfig
from uwtools.utils.file import FORMAT


def test_compare():
Expand Down Expand Up @@ -77,14 +78,16 @@ def test_realize_to_dict():
"input_format": "fmt1",
"update_config": None,
"update_format": None,
"key_path": None,
"values_needed": True,
"total": False,
"dry_run": False,
"stdin_ok": False,
}
with patch.object(config, "_realize") as _realize:
with patch.object(config, "realize") as realize:
config.realize_to_dict(**kwargs)
_realize.assert_called_once_with(
**dict({**kwargs, **{"output_file": Path(os.devnull), "output_format": None}})
realize.assert_called_once_with(
**dict({**kwargs, **{"output_file": Path(os.devnull), "output_format": FORMAT.yaml}})
)


Expand Down
Loading
Loading