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
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
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