def _validate_field_value(cls, fv, name): if not issubclass(type(fv), FieldValue): raise AquariumModelError( "Cannot create wire because {} FieldValue is {}.".format( name, fv.__class__.__name__)) if fv.parent_class not in cls.WIRABLE_PARENT_CLASSES: raise AquariumModelError( "Cannot create wire because the {} FieldValue is has '{}' " "parent class. Only {} parent classes are wirable".format( name, fv.parent_class, cls.WIRABLE_PARENT_CLASSES))
def __init__(self, source=None, destination=None): self._validate_field_values(source, destination) if hasattr(source, "id"): from_id = source.id else: from_id = None if hasattr(destination, "id"): to_id = destination.id else: to_id = None if (source and not destination) or (destination and not source): raise AquariumModelError( "Cannot wire. Either source ({}) or destination ({}) is None". format(source, destination)) if source: if not source.role: raise AquariumModelError( "Cannot wire. FieldValue {} does not have a role".format( source.role)) elif source.role != "output": raise AquariumModelError( "Cannot wire an '{}' FieldValue as a source".format( source.role)) if destination: if not destination.role: raise AquariumModelError( "Cannot wire. FieldValue {} does not have a role".format( destination.role)) elif destination.role != "input": raise AquariumModelError( "Cannot wire an '{}' FieldValue as a destination".format( destination.role)) super().__init__( **{ "source": source, "from_id": from_id, "destination": destination, "to_id": to_id, }, active=True, )
def validate(self, raise_error=True): """Validates the plan. :param raise_error: If True, raises an AquariumModelException. If false, returns the error messages. :type raise_error: boolean :return: list of error messages :rtype: array """ errors = [] field_values = [] for op in self.operations: for fv in op.field_values: field_values.append(fv) fv_keys = [fv._primary_key for fv in field_values] for wire in self.wires: for _fvtype in ["source", "destination"]: field_value = getattr(wire, _fvtype) if field_value._primary_key not in fv_keys: msg = ( "The FieldValue of a wire Wire(rid={}).{} is missing from the " "list of FieldValues in the plan. Did you forget to add an " "operation to the plan?".format( wire._primary_key, _fvtype)) errors.append(msg) if raise_error and errors: msg = "\n".join( ["(ErrNo {}) - {}".format(i, e) for i, e in enumerate(errors)]) raise AquariumModelError( "Plan {} had the following errors:\n{}".format(self, msg)) return errors
def append_to_many(self, name: str, model: "ModelBase") -> "ModelBase": """Appends a model to the many relationship. :param name: name of the relationship or attribute :type name: str :param model: model to append :type model: ModelBase :return: None :rtype: None """ if name in self.get_relationships(): field = self.get_relationships()[name] if not model.__class__.__name__ == field.nested: raise AquariumModelError( "Cannot 'append_to_many.' Model must be a '{}' but found a '{}'" .format(field.model, model.__class__.__name__)) if field.many: val = getattr(self, name) if val is None: val = [] setattr(self, name, val) if model.rid not in [m.rid for m in getattr(self, name)]: getattr(self, name).append(model) return self
def _validate_field_values(cls, src, dest): if src: cls._validate_field_value(src, "source") if dest: cls._validate_field_value(dest, "destination") if src and dest and src.rid == dest.rid: raise AquariumModelError( "Cannot create wire because source and destination are the same " "instance.")
def is_savable(self, do_raise: bool = True) -> Tuple[bool, List[str]]: """Checks if the sample can be saved or updated. .. versionadded:: 0.1.5a17 :param do_raise: :return: """ errors = [] for k, v in self.properties.items(): if v is None and self.sample_type.field_type(k).required: errors.append("FieldValue '{}' is required.".format(k)) if do_raise and errors: raise AquariumModelError( "Cannot update/save due to the following:\n" "Sample: id={} name={} ({})\n\t{}".format( self.id, self.name, self.sample_type.name, "\n\t".join(errors))) return len(errors) == 0, errors
def field_value(self, name, role): """Returns :class:`FieldValue` with name and role. Return None if not found. """ if self.field_values: fvs = self.field_value_array(name, role) if len(fvs) == 0: return None if len(fvs) == 1: return fvs[0] msg = "More than one FieldValue found for the field value" msg += ( " of operation {}.(id={}).{}.{}. Are you sure you didn't mean to " "call 'field_value_array'?") raise AquariumModelError( msg.format(self.operation_type, self.id, role, name))
def is_savable(self, do_raise: bool = True) -> Tuple[bool, List[str]]: """Checks whether this sample has fields required by the sample type. If so, the sample can be saved or updated. .. versionadded:: 0.1.5a17 :param do_raise: raise an exception when required field values are missing :return: a boolean whether there are errors, and list of error messages :raises AquariumModelError: if do_raise is True and required fields are missing """ errors = [] for k, v in self.properties.items(): if v is None and self.sample_type.field_type(k).required: errors.append("FieldValue '{}' is required.".format(k)) if do_raise and errors: raise AquariumModelError( "Cannot update/save due to the following:\n" "Sample: id={} name={} ({})\n\t{}".format( self.id, self.name, self.sample_type.name, "\n\t".join(errors))) return len(errors) == 0, errors