feat: Python runtime interface - #651
johnchildren wants to merge 6 commits into
Conversation
|
Things to include:
|
| with runtime: | ||
| workflow_id = await runtime.save_workflow("will_fail", graph) | ||
| run_id = await runtime.start_new_run(workflow_id, {}) | ||
| with pytest.raises(ValueError) as raises: |
There was a problem hiding this comment.
I guess it's probably worth adding a custom exception here?
There was a problem hiding this comment.
I think the point here was that will_fail just raises a ValueError there is no specific I chose this
There was a problem hiding this comment.
makes sense, I'm experimenting with trying to make some richer exceptions which the locations that failed so it might make sense for them to be a custom type.
4f0f854 to
639d646
Compare
639d646 to
469821d
Compare
| if "defaults" in name: | ||
| pytest.skip("default arguments not supported") | ||
|
|
||
| run_outputs = run_workflow(name, g, inputs) |
There was a problem hiding this comment.
possibly we can just remove this function now? Or move the implementation into python
There was a problem hiding this comment.
I orginally wrote it to have a more user friendly way (hiding the storage/executor) I think with the new interface this can now be deprecated
| /// | ||
| /// # Errors | ||
| /// | ||
| /// Will |
| } | ||
|
|
||
| #[pyo3(signature = (run_id, attempt=0, /, timeout=604_800))] | ||
| async fn wait_for(&self, run_id: Uuid, attempt: u32, timeout: u64) -> PyResult<()> { |
There was a problem hiding this comment.
we return UUID from start_new_run but expect UUID,attempt with wait_for is this intended?
There was a problem hiding this comment.
Sort of, I figured as starting a new run always gives attempt 0 it wasn't necessary to return it from start_new_run (though this is a difference to the rust interface). Notice that the pyo3 signature defines a default value for attempt
Co-authored-by: Philipp Seitz <philipp.seitz@quantinuum.com>
| } | ||
|
|
||
| // TODO: I'm not sure how debuggable this is | ||
| #[pyclass(name = "RuntimeConfig")] |
There was a problem hiding this comment.
It's not really possible to create one of these objects directly right now as they only exist as arguments to new_from_config. Possibly we could start returning them from the runtime though if users want to debug it?
There was a problem hiding this comment.
>>> runtime = await new_from_config({})
Traceback (most recent call last):
File "/nix/store/d20zkzz2dwl57ncmpi89rmfbvb2cs5c9-python3-3.13.15-env/lib/python3.13/concurrent/futures/_base.py", line 460, in result
return self.__get_result()
~~~~~~~~~~~~~~~~~^^
File "/nix/store/d20zkzz2dwl57ncmpi89rmfbvb2cs5c9-python3-3.13.15-env/lib/python3.13/concurrent/futures/_base.py", line 402, in __get_result
raise self._exception
File "<python-input-2>", line 1, in <module>
runtime = await new_from_config({})
^^^^^^^^^^^^^^^^^^^^^^^^^
Exception: missing field `asset_storage`
while processing 'config'
example error
| } | ||
| } | ||
|
|
||
| // TODO: I'm not sure how debuggable this is |
There was a problem hiding this comment.
>>> with runtime:
... id = await runtime.save_workflow(None, {})
...
Traceback (most recent call last):
File "/nix/store/d20zkzz2dwl57ncmpi89rmfbvb2cs5c9-python3-3.13.15-env/lib/python3.13/concurrent/futures/_base.py", line 460, in result
return self.__get_result()
~~~~~~~~~~~~~~~~~^^
File "/nix/store/d20zkzz2dwl57ncmpi89rmfbvb2cs5c9-python3-3.13.15-env/lib/python3.13/concurrent/futures/_base.py", line 402, in __get_result
raise self._exception
File "<python-input-7>", line 2, in <module>
id = await runtime.save_workflow(None, {})
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: AttributeError: 'dict' object has no attribute 'model_dump_json'
while processing 'workflow'
| } | ||
| } | ||
|
|
||
| fn __enter__(&mut self) { |
There was a problem hiding this comment.
This isn't working quite as intended:
with runtime:
...
with runtime:
...Doesn't work as we consume the event listener. Possibly a fixable bug but a kind of annoying design flaw otherwise.
| } | ||
| } | ||
|
|
||
| // TODO: I'm not sure how debuggable this is |
There was a problem hiding this comment.
>>> with runtime:
... wf_id = await runtime.save_workflow(None, compile_simulate())
... run_id = await runtime.start_new_run(wf_id, {"a": max})
...
Traceback (most recent call last):
File "/nix/store/d20zkzz2dwl57ncmpi89rmfbvb2cs5c9-python3-3.13.15-env/lib/python3.13/concurrent/futures/_base.py", line 460, in result
return self.__get_result()
~~~~~~~~~~~~~~~~~^^
File "/nix/store/d20zkzz2dwl57ncmpi89rmfbvb2cs5c9-python3-3.13.15-env/lib/python3.13/concurrent/futures/_base.py", line 402, in __get_result
raise self._exception
File "<python-input-14>", line 3, in <module>
run_id = await runtime.start_new_run(wf_id, {"a": max})
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: failed to extract enum ValueOrMappingOrBytes ('dict[str, bytes] | ValueOrBytes')
- variant BytesMapping (dict[str, bytes]): TypeError: failed to extract field ValueOrMappingOrBytes::BytesMapping.0, caused by TypeError: 'builtin_function_or_method' object is not an instance of 'bytes'
- variant ValueOrBytes (ValueOrBytes): TypeError: failed to extract field ValueOrMappingOrBytes::ValueOrBytes.0, caused by TypeError: failed to extract enum ValueOrMapping ('Mapping | Value')
- variant Mapping (Mapping): TypeError: failed to extract field ValueOrMapping::Mapping.0, caused by TypeError: failed to extract enum Value ('bool | int | float | str | complex | Sequence | Mapping')
- variant Bool (bool): TypeError: failed to extract field Value::Bool.0, caused by TypeError: 'builtin_function_or_method' object is not an instance of 'bool'
- variant Int (int): TypeError: failed to extract field Value::Int.0, caused by TypeError: 'builtin_function_or_method' object cannot be interpreted as an integer
- variant Float (float): TypeError: failed to extract field Value::Float.0, caused by TypeError: must be real number, not builtin_function_or_method
- variant String (str): TypeError: failed to extract field Value::String.0, caused by TypeError: 'builtin_function_or_method' object is not an instance of 'str'
- variant Complex (complex): TypeError: failed to extract field Value::Complex.0, caused by TypeError: must be real number, not builtin_function_or_method
- variant List (Sequence): TypeError: failed to extract field Value::List.0, caused by TypeError: 'builtin_function_or_method' object is not an instance of 'Sequence'
- variant Dict (Mapping): TypeError: failed to extract field Value::Dict.0, caused by TypeError: 'builtin_function_or_method' object is not an instance of 'dict'
- variant Value (Value): TypeError: failed to extract field ValueOrMapping::Value.0, caused by TypeError: failed to extract enum Value ('bool | int | float | str | complex | Sequence | Mapping')
- variant Bool (bool): TypeError: failed to extract field Value::Bool.0, caused by TypeError: 'dict' object is not an instance of 'bool'
- variant Int (int): TypeError: failed to extract field Value::Int.0, caused by TypeError: 'dict' object cannot be interpreted as an integer
- variant Float (float): TypeError: failed to extract field Value::Float.0, caused by TypeError: must be real number, not dict
- variant String (str): TypeError: failed to extract field Value::String.0, caused by TypeError: 'dict' object is not an instance of 'str'
- variant Complex (complex): TypeError: failed to extract field Value::Complex.0, caused by TypeError: must be real number, not dict
- variant List (Sequence): TypeError: failed to extract field Value::List.0, caused by TypeError: 'dict' object is not an instance of 'Sequence'
- variant Dict (Mapping): TypeError: failed to extract field Value::Dict.0, caused by TypeError: failed to extract enum Value ('bool | int | float | str | complex | Sequence | Mapping')
- variant Bool (bool): TypeError: failed to extract field Value::Bool.0, caused by TypeError: 'builtin_function_or_method' object is not an instance of 'bool'
- variant Int (int): TypeError: failed to extract field Value::Int.0, caused by TypeError: 'builtin_function_or_method' object cannot be interpreted as an integer
- variant Float (float): TypeError: failed to extract field Value::Float.0, caused by TypeError: must be real number, not builtin_function_or_method
- variant String (str): TypeError: failed to extract field Value::String.0, caused by TypeError: 'builtin_function_or_method' object is not an instance of 'str'
- variant Complex (complex): TypeError: failed to extract field Value::Complex.0, caused by TypeError: must be real number, not builtin_function_or_method
- variant List (Sequence): TypeError: failed to extract field Value::List.0, caused by TypeError: 'builtin_function_or_method' object is not an instance of 'Sequence'
- variant Dict (Mapping): TypeError: failed to extract field Value::Dict.0, caused by TypeError: 'builtin_function_or_method' object is not an instance of 'dict'
while processing 'inputs'
Adds a pythonic interface to the runtime that can be used when a user wants to use the runtime in their python interpreter. The API should be flexible enough to be usable with runtime daemons running on the users system or remotely in future.