예제 #1
0
    def arguments(self):
        "The arguments of the Job, as a dict of names to Python primitives or Workflows objects."
        if self.version != __version__:
            raise NotImplementedError(
                f"Accessing the `arguments` of a Job from a different version is not supported. "
                f"This Job {self.id!r} was created by client version {self.version!r}, "
                f"but you're currently running {__version__!r}.")

        if self._arguments is None:
            if len(self._message.arguments) == 0:
                arg_grafts = {}
            else:
                arg_grafts = {}
                kwarg_types = self.object.kwarg_types
                for name, json_graft in self._message.arguments.items():
                    try:
                        graft = json.loads(json_graft)
                    except json.JSONDecodeError as e:
                        raise ValueError(
                            f"Invalid JSON in graft for argument {name!r}: {e}. Value: {json_graft!r}."
                        )

                    obj = (kwarg_types.get(name, Any)._from_graft(
                        graft_client.isolate_keys(graft)) if
                           not (graft_syntax.is_literal(graft) or
                                graft_syntax.is_quoted_json(graft)) else graft)
                    arg_grafts[name] = obj

            self._arguments = arg_grafts

        return self._arguments
예제 #2
0
def arguments_to_grafts(**arguments: Proxytype) -> Dict[str, dict]:
    """
    Convert a dict of Proxytype arguments into a dict of grafts or literals.

    If an argument's graft is a literal (like ``{"0": 1.234, "returns": "0"}``),
    the literal is JSON-encoded directly rather than wrapping it in a graft, to prevent
    graft bloat, and improve browser cache hits on query argument.

    Parameters
    ----------
    arguments: Proxytype
        Arguments to use while computing.

        Each argument must be the name of a parameter created with `~.identifier.parameter`.
        Each value must be a `Proxytype` (like `~.geospatial.Image` or `.Timedelta`).
        The values cannot themselves depend on any parameters.

    Returns
    -------
    grafts: dict[str, str]
        Dict of arguments, where keys are argument names, and values
        are their graft representations. Meant to be compatible with
        `merge_value_grafts` from the graft client.

    Raises
    ------
    ValueError:
        If an argument depends on parameters.
    """
    graftables = {}
    for name, arg in arguments.items():
        # Check arguments don't themselves depend on params
        if arg.params:
            param_names = tuple(p._name for p in arg.params)
            raise ValueError(
                f"Arguments to a computation cannot depend on parameters, but the argument for {name!r} depends on "
                f"the parameters {param_names}.\n"
                f"Consider turning the object you're passing in for {name!r} into a Function, "
                f"by passing it into `wf.Function.from_object`. Then call that Function with the values you want set "
                f"for those parameters {param_names}. Then pass the result of *that* into here as `{name}=`.\n\n"
                f"Example:\n"
                f"# assume `{name}` is a variable holding whatever you just passed in as `{name}=`"
                f"{name}_function = wf.Function.from_object({name})\n"
                f"{name}_value = {name}_function({', '.join(f'<value for {n!r}>' for n in param_names)})\n"
                f"wf.compute(..., {name}={name}_value)  # same form for .visualize or .inspect"
            )

        graft = arg.graft

        # Turn value grafts of literals back into their literals, for concision and URL stability.
        # (Basically passing in `Int(1)` is the same as passing in `1`.)
        return_expr = graft[graft["returns"]]
        if graft_syntax.is_literal(return_expr) or graft_syntax.is_quoted_json(
                return_expr):
            graft = return_expr

        graftables[name] = graft

    return graftables
예제 #3
0
def parameters_to_grafts(**parameters):
    """
    Convert a dict of parameters into a dict of grafts or literals.

    If a parameter is a graft literal (i.e., a Python primitive),
    it's JSON-encoded directly rather than wrapping it in a graft, to prevent
    graft bloat, and improve browser cache hits on query argument.

    Otherwise, ``value_graft`` is called on it, so it should be a `Proxytype`
    or a JSON literal.

    If ``value_graft`` fails, `proxify` is called as a last resort to try to
    convert the value into something that graft can represent.

    Parameters
    ----------
    parameters: JSON-serializable value, Proxytype, `proxify` compatible value
        Parameters to use while computing.

        Each argument must be the name of a parameter created with `~.identifier.parameter`.
        Each value must be a JSON-serializable type (``bool``, ``int``, ``float``,
        ``str``, ``list``, ``dict``, etc.), a `Proxytype` (like `~.geospatial.Image` or `.Timedelta`),
        or a value that `proxify` can handle (like a ``datetime.datetime``).

    Returns
    -------
    grafts: dict[str, str]
        Dict of parameters, where keys are argument names, and values
        are their graft representations. Meant to be compatible with
        `merge_value_grafts` from the graft client.

    Raises
    ------
    TypeError:
        If a parameter value can't be represented as a graft by ``value_graft`` or `proxify`.
    """
    grafts = {}
    for name, param in six.iteritems(parameters):
        if graft_syntax.is_literal(param) or graft_syntax.is_graft(param):
            graftable = param
        else:
            try:
                graftable = graft_client.value_graft(param)
            except TypeError:
                try:
                    graftable = proxify(param).graft
                except NotImplementedError:
                    raise TypeError(
                        "Invalid type for parameter {!r}: {}. "
                        "Must be a JSON-serializable value, Proxytype, "
                        "or object that `proxify` can handle. "
                        "Got: {}".format(name, type(param), param))

        grafts[name] = graftable

    return grafts