def cast(self, value: Any) -> Any: """Convert the given value into a numeric value. Raises an error if the value cannot be converted to the respective numeric type of if it does not satisfy the optional range constraint. Parameters ---------- value: any User-provided value for a template parameter. Returns ------- sting, float, or int Raises ------ flowserv.error.InvalidArgumentError """ if value in ['-inf', 'inf']: value = float(value) elif self.dtype == PARA_INT: try: value = int(value) except (TypeError, ValueError): raise err.InvalidArgumentError("no int '{}'".format(value)) else: try: value = float(value) except (TypeError, ValueError): raise err.InvalidArgumentError("no float '{}'".format(value)) if self.constraint is not None: if not self.constraint.validate(value): msg = '{} not in {}'.format(value, self.constraint.to_string()) raise err.InvalidArgumentError(msg) return value
def cast(self, value: Union[List[str, Dict], Tuple[str, Dict]]) -> WorkflowStep: """Convert the given serialization into a workflow step. The given tuple contains the workflow step type identifier (str) and a type-specific serialization of the step properties. For values that represent a :class:`flowserv.model.workflow.step.ContainerStep` the dictionary elements are: `image`, `commands`, and `env`. The first two elements are mandatory. Parameters ---------- value: list or tuple with str and dict Pair of workflow step type identifier and type-specific values. Returns ------- flowserv.model.workflow.step.WorkflowStep """ if isinstance(value, ContainerStep): return value step_type, step_val = value if step_type == CONTAINER_STEP: try: return ContainerStep(image=step_val['image'], commands=step_val['commands'], env=step_val.get('env')) except KeyError as ex: raise err.InvalidArgumentError(str(ex)) raise err.InvalidArgumentError( "unknown workflow step type '{}'".format(step_type))
def cast(self, value: Any) -> Dict: """Convert the given value into a record. Returns a dictionary that is a mapping of filed identifier to the converted values returned by the respective parameter declaration. Expects a list of dictionaries containing two elements: 'name' and 'value'. The name identifies the record field and the value is the argument value for that field. Raises an error if the value is not a list, if any of the dictionaries are not well-formed, if required fields are not present in the given list, or if the respective parameter declaration for a record fields raised an exception during cast. Parameters ---------- value: any User-provided value for a template parameter. Returns ------- sting Raises ------ flowserv.error.InvalidArgumentError """ if not isinstance(value, list): raise err.InvalidArgumentError('invalid argument type') result = dict() # Cast all given values using their respective parameter declaration. for obj in value: util.validate_doc(obj, mandatory=['name', 'value'], exception=err.InvalidArgumentError) name = obj['name'] if name not in self.fields: raise err.InvalidArgumentError( "unknown argument '{}'".format(name)) result[name] = self.fields[name].cast(obj['value']) # Add default values for missing fields. for key, para in self.fields.items(): if key not in result: if para.default is not None: result[key] = para.cast(para.default) elif para.required: raise err.InvalidArgumentError( "missing field '{}'".format(key)) return result
def cast(self, value: Any) -> Any: """Convert the given value into a Boolean value. Converts string values to Boolean True if they match either of the string representations '1', 't' or 'true' (case-insensitive) and to False if the value is None or it matches '', '0', 'f' or 'false'. Raises an error if a given value is not a valid representation for a Boolean value. Parameters ---------- value: any User-provided value for a template parameter. Returns ------- sting Raises ------ flowserv.error.InvalidArgumentError """ if value is None: return False if isinstance(value, bool): return value strvalue = str(value).lower() if strvalue in ['1', 't', 'true']: return True elif strvalue in ['', '0', 'f', 'false']: return False raise err.InvalidArgumentError("not a Boolean '{}'".format(value))
def cast(self, value: Union[IOHandle, Tuple[IOHandle, str]]): """Get an instance of the InputFile class for a given argument value. The input value can either be a string (filename) or a dictionary. Parameters ---------- value: tuple of flowserv.model.files.base.IOHandle, str Handle for a file object andoptional user-provided target path. If the target path is None the defined target path is used or the defined default value. If neither is given an error is raised. Returns ------- flowserv.model.parameter.files.InputFile Raises ------ flowserv.error.InvalidArgumentError flowserv.error.UnknownFileError """ if not isinstance(value, tuple): value = (value, None) source, target = value # Ensure that the target path is set. if target is None: if self.target is not None: target = self.target elif self.default is not None: target = self.default else: raise err.InvalidArgumentError('missing target path') # The InputFile constructor may raise a TypeError if the source # argument is not a string. try: return InputFile(source=source, target=target) except TypeError as ex: raise err.InvalidArgumentError(str(ex))
def cast(self, value: Any) -> Any: """Ensure that the given value is valid. If the value is not contained in the enumerated list of values an error is raised. Parameters ---------- value: any User-provided value for a template parameter. Returns ------- sting Raises ------ flowserv.error.InvalidArgumentError """ for val in self.values: if val['value'] == value: return value raise err.InvalidArgumentError("unknown value '{}'".format(value))
def cast(self, value: ActorValue) -> ActorValue: """Ensure that the given value is an instance of the actor value class :class:`flowserv.model.parameter.actor.ActorValue`. Serializations of workflow steps are implementation dependent. For this reason, the function does not further validate the contents of the serialized workglow step. Raises an InvalidArgumentError if the argument value is not a dictionary. Parameters ---------- value: flowserv.model.parameter.actor.ActorValue Argument value for an actor parameter. Returns ------- flowserv.model.parameter.actor.ActorValue """ if not isinstance(value, ActorValue): raise err.InvalidArgumentError( "invalid actor value '{}'".format(value)) return value
def cast(self, value: List) -> List: """Convert the given value into a list where each value in the given list has been converted using the parameter declaration for the list parameter. Raises an error if the value is not a list or if the associated parameter declaration raised an exception during cast. Parameters ---------- value: any User-provided value for a template parameter. Returns ------- list Raises ------ flowserv.error.InvalidArgumentError """ if not isinstance(value, list): raise err.InvalidArgumentError('invalid argument type') return [self.para.cast(v) for v in value]
def start_run(self, arguments: Dict, config: Optional[Dict] = None, poll_interval: Optional[int] = None) -> Run: """Run the associated workflow for the given set of arguments. Parameters ---------- arguments: dict Dictionary of user-provided arguments. config: dict, default=None Optional implementation-specific configuration settings that can be used to overwrite settings that were initialized at object creation. poll_interval: int, default=None Optional poll interval that is used to check the state of a run until it is no longer in active state. Returns ------- flowserv.client.app.run.Run """ arguments = self._parameters.set_defaults(arguments=arguments) with self.service() as api: # Upload any argument values as files that are either of type # StringIO or BytesIO. arglist = list() for key, val in arguments.items(): # Convert arguments to the format that is expected by the run # manager. We pay special attention to file parameters. Input # files may be represented as strings, IO buffers or file # objects. para = self._parameters.get(key) if para is None: raise err.UnknownParameterError(key) if para.is_file(): # Upload a given file prior to running the application. upload_file = None target = None if isinstance(val, str): upload_file = FSFile(val) elif isinstance(val, StringIO): buf = BytesIO(val.read().encode('utf8')) upload_file = IOBuffer(buf) elif isinstance(val, BytesIO): upload_file = IOBuffer(val) elif isinstance(val, IOHandle): upload_file = val else: msg = 'invalid argument {} for {}'.format(key, val) raise err.InvalidArgumentError(msg) fh = api.uploads().upload_file(group_id=self.group_id, file=upload_file, name=key) val = serialize_fh(fh[filelbls.FILE_ID], target=target) arglist.append(serialize_arg(key, val)) # Execute the run and return the serialized run handle. run = api.runs().start_run(group_id=self.group_id, arguments=arglist, config=config) rh = Run(doc=run, service=self.service) # Wait for run to finish if active an poll interval is given. while poll_interval and rh.is_active(): time.sleep(poll_interval) rh = self.poll_run(run_id=rh.run_id) pprun = self.get_postproc_results() if pprun is not None: while poll_interval and pprun.is_active(): time.sleep(poll_interval) pprun = self.get_postproc_results() return rh