[docs]defmd5_hash_state(input_obj:Any)->str:"""Hash LiveFlow object's state"""# Convert obj to strinput_str=str(input_obj)# Create an MD5 hash objectmd5_hash=hashlib.md5()# Update the hash object with the bytes of the input stringmd5_hash.update(input_str.encode("utf-8"))# Get the hexadecimal representation of the hashreturnmd5_hash.hexdigest()
[docs]classValidatableMixin(ABC):def__init__(self):# Ensure any other mixins are also initializedsuper().__init__()self._last_state_hash=None# Used for LiveFlowItem state trackingself._validators:List[IFlowValidator]=[]
[docs]defadd_validator(self,validator:IFlowValidator)->"ValidatableMixin":self._validators.append(validator)ifvalidator.validate_immediately:# Validate immediately when a new validator is addedself.validate(force_live=True)# Allows for method chainingreturnself
[docs]defget_validators(self):"""Get the validators for the current validatable item."""returnself._validators
[docs]defvalidate(self,force_live:bool=False):""" Validate the current flow item and its children. This method performs validation on the current flow item and its children. If the item is an instance of LiveFlowItem, it uses an MD5 hash to track the state of the item's value. Validation is only performed if the state has changed or if the `force_live` parameter is set to True. Parameters: force_live (bool): If True, forces validation for LiveFlowItem instances regardless of whether the state has changed. This is useful when a new validator is added and immediate validation is required. Raises: FlowItemValidationError: If any of the validators fail. """# Early return if no validators - no need to access valueifnotself._validators:returnifisinstance(self,items.LiveFlowItem):current_value=self._get_value()state_hash=md5_hash_state(current_value)# Check if state has changed and we need to re-validateifnotforce_liveandstate_hash==self._last_state_hash:return# We don't need to validate self or childrenelse:self._last_state_hash=state_hashelse:current_value=self.valueself._validate_self(current_value)self._validate_children(current_value)