11import os
22import shutil
33from collections import OrderedDict
4- from typing import List , Union
4+ from typing import Dict , List , Union
55
66import numpy as np
77import xarray as xr
@@ -278,7 +278,7 @@ def add_yaml_file(self, package, yaml, template_replacements=None):
278278
279279 def map_yaml_options (self , options , config_model ):
280280 """
281- A mapping between model config options between different models. This
281+ A mapping between model config options from different models. This
282282 method should be overridden for situations in which yaml config
283283 options have diverged in name or structure from their counterparts in
284284 another model (e.g. when translating from MPAS-Ocean namelist options
@@ -304,7 +304,7 @@ def map_yaml_options(self, options, config_model):
304304
305305 def map_yaml_configs (self , configs , config_model ):
306306 """
307- A mapping between model config options between different models. This
307+ A mapping between model config options from different models. This
308308 method should be overridden for situations in which yaml config
309309 options have diverged in name or structure from their counterparts in
310310 another model (e.g. when translating from MPAS-Ocean namelist options
@@ -328,6 +328,29 @@ def map_yaml_configs(self, configs, config_model):
328328 """
329329 return configs
330330
331+ def map_yaml_streams (self , streams , config_model ):
332+ """
333+ A mapping between model streams from different models. This method
334+ should be overridden for situations in which yaml streams have diverged
335+ in name or structure from their counterparts in another model (e.g.
336+ when translating from MPAS-Ocean streams to Omega IOStreams)
337+
338+ Parameters
339+ ----------
340+ streams : dict
341+ A nested dictionary of streams data
342+
343+ config_model : str or None
344+ If streams are available for multiple models, the model that the
345+ streams are from
346+
347+ Returns
348+ -------
349+ configs : dict
350+ A revised nested dictionary of streams data
351+ """
352+ return streams
353+
331354 def map_yaml_to_namelist (self , options ):
332355 """
333356 A mapping from yaml model config options to namelist options. This
@@ -443,7 +466,7 @@ def runtime_setup(self):
443466 self .dynamic_model_config (at_setup = False )
444467
445468 if self .make_yaml :
446- self ._process_yaml (quiet = quiet )
469+ self ._process_yaml (quiet = quiet , remove_unrequested_streams = False )
447470 else :
448471 self ._process_namelists (quiet = quiet )
449472 self ._process_streams (quiet = quiet , remove_unrequested = False )
@@ -484,7 +507,7 @@ def process_inputs_and_outputs(self):
484507 self ._create_model_config ()
485508
486509 if self .make_yaml :
487- self ._process_yaml (quiet = quiet )
510+ self ._process_yaml (quiet = quiet , remove_unrequested_streams = True )
488511 else :
489512 self ._process_namelists (quiet = quiet )
490513 self ._process_streams (quiet = quiet , remove_unrequested = True )
@@ -749,7 +772,7 @@ def _process_yaml_streams(self, yaml_filename, package, replacements,
749772 tree = polaris .streams .update_tree (tree , new_tree )
750773 return tree
751774
752- def _process_yaml (self , quiet ):
775+ def _process_yaml (self , quiet , remove_unrequested_streams ):
753776 """
754777 Processes changes to a yaml file from the files and dictionaries
755778 in the step's ``model_config_data``.
@@ -764,6 +787,8 @@ def _process_yaml(self, quiet):
764787 if not quiet :
765788 print (f'Warning: replacing yaml options in { self .yaml } ' )
766789
790+ streams : Dict [str , Dict [str , Union [str , float , int , List [str ]]]] = {}
791+
767792 for entry in self .model_config_data :
768793 if 'namelist' in entry :
769794 raise ValueError ('Cannot generate a yaml config from an MPAS '
@@ -785,7 +810,42 @@ def _process_yaml(self, quiet):
785810
786811 configs = self .map_yaml_configs (configs = yaml .configs ,
787812 config_model = config_model )
813+ new_streams = self .map_yaml_streams (
814+ streams = yaml .streams , config_model = config_model )
815+ self ._update_yaml_streams (streams , new_streams ,
816+ quiet = quiet ,
817+ remove_unrequested = False )
788818 self ._yaml .update (configs = configs , quiet = quiet )
819+ self ._update_yaml_streams (
820+ self ._yaml .streams , streams , quiet = quiet ,
821+ remove_unrequested = remove_unrequested_streams )
822+
823+ @staticmethod
824+ def _update_yaml_streams (streams , new_streams , quiet , remove_unrequested ):
825+ """
826+ Update yaml streams, optionally removing any streams that aren't in
827+ new_streams
828+ """
829+
830+ for stream_name , new_stream in new_streams .items ():
831+ if stream_name in streams :
832+ streams [stream_name ].update (new_stream )
833+ if not quiet :
834+ print (f' updating: { stream_name } ' )
835+ else :
836+ if not quiet :
837+ print (f' adding: { stream_name } ' )
838+ streams [stream_name ] = new_stream
839+
840+ if remove_unrequested :
841+ # during setup, we remove any default streams that aren't requested
842+ # but at runtime we don't want to do this because we would lose any
843+ # streams added only during setup.
844+ for stream_name in list (streams .keys ()):
845+ if stream_name not in new_streams :
846+ if not quiet :
847+ print (f' dropping: { stream_name } ' )
848+ streams .pop (stream_name )
789849
790850
791851def make_graph_file (mesh_filename , graph_filename = 'graph.info' ,
0 commit comments