Source code for multilevel_py.clabject_prop

from inspect import signature as sig
from typing import Tuple, Union, List, Any
from abc import abstractmethod

from multilevel_py.constraints import PropValueConstraint, ReInitPropConstr
from multilevel_py.exceptions import InvalidMultiplicityTupleException, InvalidPropValueConstraintException


[docs]class BaseClabjectProp: """ Base class of a ClabjectProp, i.e. an enhanced attribute that is capable of "deferred instantiation" """
[docs] def __init__(self, prop_name: str, steps_to_instantiation: int, steps_from_instantiation: Union[int, float], constraints: List[PropValueConstraint] = [], is_final: bool = False, prop_value: Any = None, default_value: Any = None ): """ Args: prop_name: The name of the property, which must be unique for the given clabject steps_to_instantiation: The number of steps until the property is instantiated, i.e. assigned with a value. A value of 1 means that the property has to be instantiated in the next instantiation step. steps_from_instantiation: The number of steps the property continues to exist down the intantiation chain after being instantiated. If set to 0 the property appears only at the clabject it was instantiated on. If set to math.inf it is visible for all direct and indirect instances down the instantiation hierarchy. constraints: A List of PropValueConstraints that restrict the space of acceptable property values. A value is only set or updated if it passes through all constraints, otherwise a :class:`exceptions.ConstraintViolationException` is thrown is_final: Indicating whether the property can be changed after its first instantiation. prop_value: The value that is assigned to the property during an instantiation step. Can be any python object including functions. default_value: optional default_value of the property, used at instantiation if no prop_value is provided """ assert steps_to_instantiation >= 0 assert steps_from_instantiation >= 0 assert isinstance(constraints, list) from multilevel_py.constraints import PropValueConstraint for constr in constraints: if not isinstance(constr, PropValueConstraint): raise InvalidPropValueConstraintException(constr=constr) assert isinstance(is_final, bool) self.prop_name = prop_name self.steps_to_instantiation = steps_to_instantiation self.steps_from_instantiation = steps_from_instantiation self.constraints = constraints self.is_final = is_final self.prop_value = prop_value self.default_value = default_value self.re_init_prop_constr: ReInitPropConstr = None for ts_constr in self.type_specific_constraints(): ts_constr.type_specific = True self.constraints.append(ts_constr)
[docs] @abstractmethod def type_specific_constraints(self) -> List[PropValueConstraint]: """ Declare type specific constraints that will be appended to self.constraints """ pass
[docs] @abstractmethod def get_viz_value_str(self) -> str: """ Returns: a concrete syntax friendly string for the given prop value """ pass
[docs]class SimpleProp(BaseClabjectProp): """ A property of a Clabject, that is meant to hold a simple (single primitive) value """ def __init__(self, prop_name: str, steps_to_instantiation: int, steps_from_instantiation: Union[int, float], constraints: List[PropValueConstraint] = [], is_final: bool = False, prop_value: Any = None, default_value: Any = None ): super(SimpleProp, self).__init__( prop_name=prop_name, steps_to_instantiation=steps_to_instantiation, steps_from_instantiation=steps_from_instantiation, constraints=constraints, is_final=is_final, prop_value=prop_value, default_value=default_value )
[docs] def type_specific_constraints(self): return []
[docs] def get_viz_value_str(self): return str(self.prop_value)
[docs]class AssociationProp(BaseClabjectProp): """ A Property of a clabjec that is meant to hold an associated clabject """ def __init__(self, prop_name: str, steps_to_instantiation: int, steps_from_instantiation: Union[int, float], constraints: List[PropValueConstraint] = [], is_final: bool = False, prop_value: Any = None, default_value: Any = None ): super(AssociationProp, self).__init__( prop_name=prop_name, steps_to_instantiation=steps_to_instantiation, steps_from_instantiation=steps_from_instantiation, constraints=constraints, is_final=is_final, prop_value=prop_value, default_value=default_value )
[docs] def type_specific_constraints(self): from multilevel_py.core import is_clabect_or_empty_constr return [is_clabect_or_empty_constr]
[docs] def get_viz_value_str(self): return "Associated Clabject: " + str(self.prop_value)
[docs]class CollectionDescription: """ Defines a collection property in terms of multiplicity and collection member constraints """
[docs] def __init__(self, min_max: Tuple[int, int] = (), member_value_constr=None): """ Args: min_max: A tuple with defining the min and max number of collection members (inclusive logic) member_value_constr: A PropValueConstraint that is applied on all collection members """ self.min_max = min_max self.member_value_constr = member_value_constr
[docs]class CollectionProp(BaseClabjectProp): """ A property of a clabject that is meant to hold a collection, i.e. a multi-value property of a Clabject """ def __init__(self, prop_name: str, steps_to_instantiation: int, steps_from_instantiation: Union[int, float], constraints: List[PropValueConstraint] = [], is_final: bool = False, prop_value: Any = None, default_value: Any = None, collection_desc: CollectionDescription = None, ): assert isinstance(collection_desc, CollectionDescription) self.collection_desc = collection_desc self.collection_member_constr = None super(CollectionProp, self).__init__( prop_name=prop_name, steps_to_instantiation=steps_to_instantiation, steps_from_instantiation=steps_from_instantiation, constraints=constraints, is_final=is_final, prop_value=prop_value, default_value=default_value ) if collection_desc.min_max: if not (len(collection_desc.min_max) == 2 and ( 0 <= collection_desc.min_max[0] <= collection_desc.min_max[1])): raise InvalidMultiplicityTupleException(provided_tuple=collection_desc) self.collection_desc = collection_desc self.collection_member_constr = None
[docs] def type_specific_constraints(self): _constraints = [] if self.collection_desc is not None: from multilevel_py.constraints import is_collection_constraint _constraints.append(is_collection_constraint) if self.collection_desc.min_max: from multilevel_py.constraints import prop_constraint_collection_multiplicity_functional mult_constr = prop_constraint_collection_multiplicity_functional( min_member_number=self.collection_desc.min_max[0], max_member_number=self.collection_desc.min_max[1], eval_on_init=False ) _constraints.append(mult_constr) if self.collection_desc.member_value_constr: from multilevel_py.constraints import prop_constraint_collection_member_functional self.collection_member_constr = prop_constraint_collection_member_functional( member_constr_func=self.collection_desc.member_value_constr, eval_on_init=True) _constraints.append(self.collection_member_constr) return _constraints
[docs] def get_viz_value_str(self): return str(self.prop_value)
[docs]class MethodProp(BaseClabjectProp): """ A property of a clabject that is meant to hold a method object """ def __init__(self, prop_name: str, steps_to_instantiation: int, steps_from_instantiation: Union[int, float], constraints: List[PropValueConstraint] = [], is_final: bool = False, prop_value: Any = None, default_value: Any = None ): super(MethodProp, self).__init__( prop_name=prop_name, steps_to_instantiation=steps_to_instantiation, steps_from_instantiation=steps_from_instantiation, constraints=constraints, is_final=is_final, prop_value=prop_value, default_value=default_value )
[docs] def type_specific_constraints(self): from multilevel_py.constraints import value_can_be_bound_as_method_constraint return [value_can_be_bound_as_method_constraint]
[docs] def get_viz_value_str(self): res_str = str(self.prop_value) if hasattr(self.prop_value, "__impl_origin__"): res_str = "Impl. from " + self.prop_value.__impl_origin__ + ": " + \ self.prop_value.__name__ + str(sig(self.prop_value)) return res_str
[docs]class StateConstraintProp(BaseClabjectProp): """ A property of a Clabject, that is meant to hold a StateConstraint """ def __init__(self, prop_name: str, steps_to_instantiation: int, steps_from_instantiation: Union[int, float], constraints: List[PropValueConstraint] = [], is_final: bool = False, prop_value: Any = None, default_value: Any = None ): super(StateConstraintProp, self).__init__( prop_name=prop_name, steps_to_instantiation=steps_to_instantiation, steps_from_instantiation=steps_from_instantiation, constraints=constraints, is_final=is_final, prop_value=prop_value, default_value=default_value )
[docs] def type_specific_constraints(self): from .constraints import prop_constraint_py_isinstance_functional from .constraints import ClabjectStateConstraint is_clabject_state_constraint = prop_constraint_py_isinstance_functional(ClabjectStateConstraint, True) return [is_clabject_state_constraint]
[docs] def get_viz_value_str(self): res_str = "StateConstraint: " + str(self.prop_value.name) return res_str