Source code for glotaran.model.property

"""The model property class."""

import typing

from glotaran.parameter import Parameter

from .util import wrap_func_as_method


[docs]class ModelProperty(property): def __init__(self, cls, name, prop_type, doc, default, allow_none): self._name = name self._allow_none = allow_none self._determine_if_parameter(prop_type) set_type = prop_type if not self._is_parameter else typing.Union[str, prop_type] @wrap_func_as_method(cls, name=name) def setter(that_self, value: set_type): if value is None and not self._allow_none: raise Exception( f"Property '{name}' of '{cls.__name__}' is not allowed to set to None." ) if self._is_parameter and value is not None: if self._is_parameter_value and isinstance(value, str): value = Parameter(full_label=str(value)) elif self._is_parameter_list and all(isinstance(v, str) for v in value): value = [Parameter(full_label=str(v)) for v in value] elif self._is_parameter_dict and all(isinstance(v, str) for v in value.values()): for k, v in value.items(): value[k] = Parameter(full_label=v) setattr(that_self, f"_{self._name}", value) @wrap_func_as_method(cls, name=name) def getter(that_self) -> prop_type: value = getattr(that_self, f"_{self._name}") if value is None: value = default return value super().__init__(fget=getter, fset=setter, doc=doc) @property def allow_none(self) -> bool: return self._allow_none
[docs] def validate(self, value, model, parameters=None) -> typing.List[str]: if value is None and self.allow_none: return [] missing_model = [] if hasattr(model, f"set_{self._name}") or hasattr(model, f"add_{self._name}"): attr = getattr(model, self._name) if isinstance(value, list): for item in value: if item not in attr: missing_model.append((self._name, item)) elif isinstance(value, dict): for item in value.values(): if item not in attr: missing_model.append((self._name, item)) else: if value not in attr: missing_model.append((self._name, value)) missing_model = [ f"Missing Model Item: '{name}'['{label}']" for name, label in missing_model ] missing_parameters = [] if parameters is not None and self._is_parameter and value is not None: if self._is_parameter_value: if not parameters.has(value.full_label): missing_parameters.append(value.full_label) elif self._is_parameter_list: for item in value: if not parameters.has(item.full_label): missing_parameters.append(item.full_label) elif self._is_parameter_dict: for item in value.values(): if not parameters.has(item.full_label): missing_parameters.append(item.full_label) missing_parameters = [f"Missing Parameter: '{p}'" for p in missing_parameters] return missing_model + missing_parameters
[docs] def fill(self, value, model, parameter): if value is None: return None if self._is_parameter: if self._is_parameter_value: value.set_from_group(parameter) elif self._is_parameter_list: for v in value: v.set_from_group(parameter) elif self._is_parameter_dict: for v in value.values(): v.set_from_group(parameter) elif hasattr(model, self._name): if isinstance(value, list): value = [getattr(model, self._name)[v].fill(model, parameter) for v in value] elif isinstance(value, dict): value = { k: getattr(model, self._name)[v].fill(model, parameter) for (k, v) in value.items() } else: value = getattr(model, self._name)[value].fill(model, parameter) return value
def _determine_if_parameter(self, type): self._is_parameter_value = type is Parameter self._is_parameter_list = ( hasattr(type, "__origin__") and issubclass(type.__origin__, typing.List) and type.__args__[0] is Parameter ) self._is_parameter_dict = ( hasattr(type, "__origin__") and issubclass(type.__origin__, typing.Dict) and type.__args__[1] is Parameter ) self._is_parameter = ( self._is_parameter_value or self._is_parameter_list or self._is_parameter_dict )