def check_types(self): from janis_core.workflow.workflow import InputNode, StepNode stoolin: TOutput = self.start.outputs()[ self.stag ] if self.stag is not None else first_value(self.start.outputs()) ftoolin: TInput = self.finish.inputs()[ self.ftag ] if self.ftag is not None else first_value(self.finish.inputs()) stype = stoolin.outtype ftype = ftoolin.intype start_is_scattered = ( isinstance(self.start, StepNode) and self.start.scatter is not None ) if start_is_scattered: Logger.log( f"This edge merges the inputs from '{full_dot(self.start, self.stag)}' for " f"'{full_dot(self.finish, self.ftag)}'" ) stype = Array(stype) if self.scatter: if not isinstance(stype, Array): raise Exception( f"Scatter was required for '{self.start.id()}.{self.stag} → '{self.finish.id()}.{self.ftag}' but " f"the input type was {type(stype).__name__} and not an array" ) stype = stype.subtype() source_has_default = ( isinstance(self.start, InputNode) and self.start.default is not None ) # Scatters are handled automatically by the StepTagInput Array unwrapping # Merges are handled automatically by the `start_is_scattered` Array wrap self.compatible_types = ftype.can_receive_from(stype, source_has_default) if not self.compatible_types: if isinstance(ftype, Array) and ftype.subtype().can_receive_from(stype): self.compatible_types = True if not self.compatible_types: s = full_dot(self.start, self.stag) f = full_dot(self.finish, self.ftag) message = ( f"Mismatch of types when joining '{s}' to '{f}': " f"{stoolin.outtype.id()} -/→ {ftoolin.intype.id()}" ) if isinstance(stype, Array) and ftype.can_receive_from(stype.subtype()): message += " (did you forget to SCATTER?)" Logger.critical(message)
def add_source(self, start: Node, stag: Optional[str], should_scatter) -> Edge: """ Add a connection :param start: :param stag: :param should_scatter: :return: """ from janis_core.workflow.workflow import StepNode stype = ( start.outputs()[stag] if stag is not None else first_value(start.outputs()) ).outtype ftype = ( self.finish.inputs()[self.ftag] if self.ftag is not None else first_value(self.finish.inputs()) ).intype start_is_scattered = isinstance(start, StepNode) and start.scatter is not None if start_is_scattered: Logger.log( f"This edge merges the inputs from '{full_dot(start, stag)}' for " f"'{full_dot(self.finish, self.ftag)}'" ) stype = Array(stype) if should_scatter: if not isinstance(stype, Array): raise Exception( f"Scatter was required for '{start.id()}.{stag} → '{self.finish.id()}.{self.ftag}' but " f"the input type was {type(stype).__name__} and not an array" ) stype = stype.subtype() if len(self.source_map) == 1 and start.id() not in self.source_map: self.multiple_inputs = True if not isinstance(ftype, Array): raise Exception( f"Adding multiple inputs to '{self.finish.id()}' and '{ftype.id()}' is not an array" ) if not isinstance(stype, Array) and isinstance(ftype, Array): # https://www.commonwl.org/user_guide/misc/#connect-a-solo-value-to-an-input-that-expects-an-array-of-that-type self.multiple_inputs = True e = Edge(start, stag, self.finish, self.ftag, should_scatter=should_scatter) self.source_map[start.id()] = e return e