Exemple #1
0
    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
Exemple #2
0
    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))
Exemple #3
0
    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
Exemple #4
0
    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))
Exemple #5
0
    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))
Exemple #6
0
    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))
Exemple #7
0
    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
Exemple #8
0
    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]
Exemple #9
0
    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