Currently, parseable workflow python is restricted to
- Assigning variables to names
- Assigning a list to a variable / appending to it in a
for-scope
- Flow control operations (
for/while/if-elif-else/try-except)
Such that we cannot currently parse a workflow like this:
def my_wf_to_parse(a, b, c):
d = a + b
e = c + d
return e
because of the + operators.
However, this is strictly a parsing limitation, and not a workflow limitation. One can get the recipe I imaging we would want from parsing such a definition by manually constructing a node for the operator wrapping the standard library:
import operator
from pyiron_snippets import versions
from flowrep.api import schemas as frs
add_recipe = frs.AtomicNode.model_validate(
{
"inputs": ["a", "b"],
"outputs": ["result"],
"reference": {
"info": versions.VersionInfo.of(operator.add),
"restricted_input_kinds": {
"a": "POSITIONAL_ONLY",
"b": "POSITIONAL_ONLY",
},
},
}
)
Since we can use recipes in workflow definitions (#199) and basic atomic recipes are callable (#197), we can write a parseable, recipe-based definition that behaves like our target
import flowrep as fr
@fr.workflow
def my_wf(a, b, c):
d = add_recipe(a, b)
e = add_recipe(c, d)
return e
my_wf(1,2,3)
>>> 6
And is a valid, runnable recipe
from flowrep.api import tools as frt
frt.run_recipe(my_wf.flowrep_recipe, a=1, b=2, c=3).output_ports["e"].value
>>> 6
I.e., getting my_wf_to_parse to produce a valid recipe is purely a parser extension, and based around recognizing that we have an expression using an operator that ought to produce a new node, which we can dynamically produce based on the underlying builtin operator function. The example here is for +, but this pattern holds for all the standard operators.
We'd need to be careful to cross our t's and dot our i's, but from a technical perspective there is nothing particularly difficult here. But, ought we do this? In an off-grid conversation with @samwaseda, he expressed concern that in the current version of the parser, he's not clear what will parse and what won't (I suspect largely because for-loops have introduced this [] list operations). So making this sort of change would be positive in that users could write "more natural" python and have it parse, but negative in that the list of "this is what is parseable" becomes more complex and the boundaries harder to remember. Now, as long as failed parsing raises clean, clear, and helpful error messages when the parsing fails, I lean towards embracing the extra flexibility -- but there is a trade-off.
Currently, parseable workflow python is restricted to
for-scopefor/while/if-elif-else/try-except)Such that we cannot currently parse a workflow like this:
because of the
+operators.However, this is strictly a parsing limitation, and not a workflow limitation. One can get the recipe I imaging we would want from parsing such a definition by manually constructing a node for the operator wrapping the standard library:
Since we can use recipes in workflow definitions (#199) and basic atomic recipes are callable (#197), we can write a parseable, recipe-based definition that behaves like our target
And is a valid, runnable recipe
I.e., getting
my_wf_to_parseto produce a valid recipe is purely a parser extension, and based around recognizing that we have an expression using an operator that ought to produce a new node, which we can dynamically produce based on the underlying builtin operator function. The example here is for+, but this pattern holds for all the standard operators.We'd need to be careful to cross our t's and dot our i's, but from a technical perspective there is nothing particularly difficult here. But, ought we do this? In an off-grid conversation with @samwaseda, he expressed concern that in the current version of the parser, he's not clear what will parse and what won't (I suspect largely because
for-loops have introduced this[]list operations). So making this sort of change would be positive in that users could write "more natural" python and have it parse, but negative in that the list of "this is what is parseable" becomes more complex and the boundaries harder to remember. Now, as long as failed parsing raises clean, clear, and helpful error messages when the parsing fails, I lean towards embracing the extra flexibility -- but there is a trade-off.