Skip to content

Commit

Permalink
Changes as follows below:
Browse files Browse the repository at this point in the history
Moved representers to support.py
Moved OrderedDict logic to its own representer
  • Loading branch information
WeirAE committed Feb 28, 2024
1 parent 9554890 commit 173909a
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 16 deletions.
12 changes: 11 additions & 1 deletion src/uwtools/config/formats/yaml.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from collections import OrderedDict
from pathlib import Path
from types import SimpleNamespace as ns
from typing import Optional
Expand All @@ -6,7 +7,13 @@
import yaml

from uwtools.config.formats.base import Config
from uwtools.config.support import INCLUDE_TAG, TaggedString, log_and_error, represent_namelist
from uwtools.config.support import (
INCLUDE_TAG,
TaggedString,
log_and_error,
represent_namelist,
represent_ordereddict,
)
from uwtools.utils.file import FORMAT, readable, writable

_MSGS = ns(
Expand Down Expand Up @@ -46,6 +53,8 @@ def __repr__(self) -> str:
The string representation of a YAMLConfig object.
"""
yaml.add_representer(TaggedString, TaggedString.represent)
yaml.add_representer(f90nml.namelist.Namelist, represent_namelist)
yaml.add_representer(OrderedDict, represent_ordereddict)
return yaml.dump(self.data, default_flow_style=False).strip()

# Private methods
Expand Down Expand Up @@ -118,6 +127,7 @@ def dump_dict(cfg: dict, path: Optional[Path] = None) -> None:
"""
yaml.add_representer(TaggedString, TaggedString.represent)
yaml.add_representer(f90nml.namelist.Namelist, represent_namelist)
yaml.add_representer(OrderedDict, represent_ordereddict)
with writable(path) as f:
yaml.dump(cfg, f, sort_keys=False)

Expand Down
45 changes: 31 additions & 14 deletions src/uwtools/config/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from importlib import import_module
from typing import Dict, Type, Union

import f90nml # type: ignore
import yaml

from uwtools.exceptions import UWConfigError
Expand Down Expand Up @@ -54,6 +55,36 @@ def log_and_error(msg: str) -> Exception:
return UWConfigError(msg)


def represent_namelist(dumper: yaml.Dumper, data: f90nml.Namelist) -> yaml.nodes.MappingNode:
"""
Convert f90 Namelist objects to ordered dicts and serialize.
:param dumper: The YAML dumper.
:param data: The f90nml Namelist to serialize.
"""
# Convert the f90nml Namelist to an ordered dictionary
namelist_dict = data.todict()

# Represent the dictionary as a YAML mapping
return dumper.represent_mapping("tag:yaml.org,2002:map", namelist_dict)


def represent_ordereddict(dumper: yaml.Dumper, data: OrderedDict) -> yaml.nodes.MappingNode:
"""
Convert ordered dict objects to dictionaries and serialize.
:param dumper: The YAML dumper.
:param data: The ordereddict to serialize.
"""
# Convert the Ordered Dict to a dictionary
for key, value in data.items():
if isinstance(value, OrderedDict):
data[key] = dict(value)

# Represent the dictionary as a YAML mapping
return dumper.represent_mapping("tag:yaml.org,2002:map", data)


class TaggedString:
"""
A class supporting custom YAML tags specifying type conversions.
Expand Down Expand Up @@ -89,17 +120,3 @@ def represent(dumper: yaml.Dumper, data: TaggedString) -> yaml.nodes.ScalarNode:
documentation for details.
"""
return dumper.represent_scalar(data.tag, data.value)


def represent_namelist(dumper: yaml.Dumper, data) -> yaml.nodes.MappingNode:
"""
Serialize f90nml tags.
"""
# Convert the f90nml Namelist object to a dictionary
namelist_dict = data.todict()
for key, value in namelist_dict.items():
if isinstance(value, OrderedDict):
namelist_dict[key] = dict(value)

# Represent the dictionary as a YAML mapping
return dumper.represent_mapping("tag:yaml.org,2002:map", namelist_dict)
9 changes: 8 additions & 1 deletion src/uwtools/tests/config/test_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""

import logging
from collections import OrderedDict

import f90nml # type: ignore
import pytest
Expand Down Expand Up @@ -58,11 +59,17 @@ def test_log_and_error(caplog):


def test_represent_namelist():
yaml.add_representer(f90nml.namelist.Namelist, support.represent_namelist)
namelist = f90nml.reads("&namelist\n key = value\n/\n")
assert yaml.dump(namelist, default_flow_style=True).strip() == "{namelist: {key: value}}"


def test_represent_ordereddict():
ordereddict_values = OrderedDict([("example", OrderedDict([("key", "value")]))])
assert (
yaml.dump(ordereddict_values, default_flow_style=True).strip() == "{example: {key: value}}"
)


class Test_TaggedString:
"""
Tests for class uwtools.config.support.TaggedString.
Expand Down

0 comments on commit 173909a

Please sign in to comment.