Skip to content

Commit

Permalink
Fix how yaml model config options are update
Browse files Browse the repository at this point in the history
We treat config options from files (with sections) differently
from replacement options provided in a dictionary in code.
  • Loading branch information
xylar committed Aug 7, 2024
1 parent 1f0c36c commit fd25714
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 17 deletions.
20 changes: 9 additions & 11 deletions polaris/model_step.py
Original file line number Diff line number Diff line change
Expand Up @@ -658,30 +658,28 @@ def _process_yaml(self, quiet):
if not self.model_config_data:
return

replacements = dict()
if self._yaml is None:
raise ValueError('Trying to update a yaml object but it was '
'never created.')

if not quiet:
print(f'Warning: replacing yaml options in {self.yaml}')

for entry in self.model_config_data:
if 'namelist' in entry:
raise ValueError('Cannot generate a yaml config from an MPAS '
'namelist file.')

if 'options' in entry:
# this is a dictionary of replacement namelist options
# this is a dictionary of replacement model config options
options = entry['options']
self._yaml.update(options=options, quiet=quiet)
else:
yaml = PolarisYaml.read(filename=entry['yaml'],
package=entry['package'],
replacements=entry['replacements'])
options = yaml.configs
replacements.update(options)

if not quiet:
print(f'Warning: replacing yaml options in {self.yaml}')

if self._yaml is None:
raise ValueError('Trying to update a yaml object but it was '
'never created.')
self._yaml = self._yaml.update(replacements, quiet=quiet)
self._yaml.update(configs=yaml.configs, quiet=quiet)


def make_graph_file(mesh_filename, graph_filename='graph.info',
Expand Down
54 changes: 48 additions & 6 deletions polaris/yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,23 +89,30 @@ def read(cls, filename, package=None, replacements=None):
yaml.configs = configs
return yaml

def update(self, configs, quiet=True):
def update(self, configs=None, options=None, quiet=True):
"""
Add config options from a dictionary
Parameters
----------
configs : dict
configs : dict, optional
A nested dictionary of config sections, options and values
options : dict, optional
A flat dictionary of options and values
quiet : bool, optional
Whether or not to print the updated config options as they are
replaced
"""
if self.model in configs:
# we want one layer deeper
configs = configs[self.model]
_update_section(configs, self.configs, quiet)
if configs is not None:
if self.model in configs:
# we want one layer deeper
configs = configs[self.model]
_update_section(configs, self.configs, quiet)

if options is not None:
_update_options(options, self.configs, quiet)

def write(self, filename):
"""
Expand Down Expand Up @@ -275,6 +282,41 @@ def _update_section(src, dst, quiet, print_section=None):
dst[name] = src[name]


def _update_options(src, dst, quiet):
"""
Update config options by searching in the destination nested dictionary
"""
for name in src:
success = _update_option(name, src[name], dst, quiet)
if not success:
raise ValueError(
f'Attempting to modify a nonexistent config '
f'options: {name}')


def _update_option(option, value, dst, quiet, print_section=None):
"""
Recursively attempt to find and replace the value of the
given option
"""
for name in dst:
if isinstance(dst[name], (dict, OrderedDict)):
if print_section is not None:
print_subsection = f'{print_section}: {name}'
else:
print_subsection = name
success = _update_option(option, value, dst[name], quiet,
print_subsection)
if success:
return True
elif name == option:
dst[name] = value
if not quiet:
print(f' {print_section}: {name} = {value}')
return True
return False


def _read_namelist(namelist_template, namelist_filename):
""" Read the defaults file """
record_map = _read_namelist_template(namelist_template)
Expand Down

0 comments on commit fd25714

Please sign in to comment.