Source code for TidalPy.utilities.classes.model.model_utils
import copy
from types import ModuleType
from typing import Any, Callable, Dict, Tuple, Union
from warnings import warn
from .functional_utils import is_function, parse_model_docstring
from ...dictionary_utils import nested_get
[docs]
def find_all_models(module: ModuleType, ignore_functional_types: tuple = tuple()) -> \
Tuple[Dict[str, Callable], Dict[str, Tuple[str, ...]], Dict[str, Tuple[str, ...]]]:
""" Find all functions within the provided module
Provides the user with information regarding the functions inputs.
Parameters
----------
module : ModuleType
A python module full of function definitions.
ignore_functional_types: tuple = (,)
A tuple of additional types to ignore when looking for functions.
Returns
-------
models : Dict[str, Callable]
Dictionary of function names: function.
model_const_args : Dict[str, Tuple[str, ...]]
Dictionary of function names: tuple of names of constant arguments for that function.
model_live_args : Dict[str, Tuple[str, ...]]
Dictionary of function names: tuple of names of live arguments for that function.
"""
models = dict() # type: Dict['str', Callable]
model_const_args = dict() # type: Dict[str, Tuple[str, ...]]
model_live_args = dict() # type: Dict[str, Tuple[str, ...]]
for item_name, item in module.__dict__.items():
skip = False
if type(item) in ignore_functional_types:
# Function was in the additional types to be ignored.
skip = True
else:
for ignore_func in ignore_functional_types:
if item is ignore_func:
skip = True
break
if skip:
continue
if is_function(item):
const_args, live_args = parse_model_docstring(item)
models[item_name] = item
model_const_args[item_name] = const_args
model_live_args[item_name] = live_args
return models, model_const_args, model_live_args
[docs]
def build_model_default_inputs(
const_arg_dict: Dict[str, Tuple[str, ...]], dict_of_defaults: dict,
inner_keys: Union[Tuple[str, ...], str] = None
) -> Dict[str, Dict[str, Tuple[Any, ...]]]:
""" Builds a dictionary of default input parameters using a constant argument dictionary and a dictionary of
default values.
Parameters
----------
const_arg_dict : Dict[str, Tuple[str, ...]]
Constant argument dictionary is assumed to have been built by model_utils.find_all_models.
dict_of_defaults : dict
Dictionary of default parameters, assumed to have an outer key (generally used for layer types).
inner_keys : Union[Tuple[str, ...], str] (optional)
Optional list of keys to use after the outer key to find the correct parameter sub dict.
Returns
-------
default_args_byfunc : Dict[str, Dict[str, Tuple[Any, ...]]]
Dictionary of default constant arguments, broken up by function names and then by layer types.
"""
default_args_byfunc = dict()
# Make a copy of the default dict to ensure that no values are changed or that any mutable types are stored that
# could be later changed.
dict_of_defaults = copy.deepcopy(dict_of_defaults)
for func_name, const_arg_names in const_arg_dict.items():
default_args_byfunc[func_name] = dict()
# Assume outer key is used to pick out layer types or similar
for outer_key, inner_dict in dict_of_defaults.items():
if inner_keys is not None:
# If parameters are stored in a subdict, then we need to find locate that subdict.
inner_dict = nested_get(inner_dict, nested_keys=inner_keys, raiseon_nolocate=True)
default_args = list()
force_none = False
for const_arg_name in const_arg_names:
if const_arg_name in inner_dict:
default_args.append(inner_dict[const_arg_name])
else:
# What to do if a required constant argument is not in the default dictionary.
# For now we will raise a warning.
warn(
f'Can not find the required constant parameter {const_arg_name} (used in function {func_name})'
f' for layer type {outer_key}.'
)
# Then just put make this entire functions default args == None.
force_none = True
if force_none:
default_args_byfunc[func_name][outer_key] = None
else:
default_args_byfunc[func_name][outer_key] = tuple(default_args)
return default_args_byfunc