Considering this example:
from flytekit import task, workflow
@task
def test() -> tuple[str, str, tuple[str, str]]:
return "foo", "bar", ("foo-inner", "bar-inner")
@workflow
def wf() -> tuple[str, str, tuple[str, str]]:
return test()
if __name__ == "__main__":
print(wf())
I think it would be ok to treat the “outer or main”
DefaultNamedTupleOutput
return value (that is always returned when there are multiple return values) with the existing logic and not with a potential new tuple type transformer but invoke a potential tuple type transformer only for the “inner” tuple here.
Of course it would be nice to have a general solution but I think it’s more important that users can do what is shown in the code snippet.
---
One could argue that a tuple type transformer isn’t very important, one could just return e.g. a list instead.
The problem is that changing the tuple to a list in the example above requires a user to understand that the type engine exists in the first place and what its limitations are.
The type engine works so well that most users at least early on don’t realize its there. I onboarded ~30 people onto Flyte at my previous and current company and would say that there are 3 typical situations where people first learn that the type engine exists. 1) When they try to return tuples, 2) when they put an int into a dict and get a dict with a float on the other side (maybe fixed now?) and 3) when I show them how to build a custom type transformer.
They typically find 3) super cool but also typically are (maybe unreasonably) frustrated when learning about 1 and 2. Something like “returning a tuple is the most basic python thing, why doesn’t even this work?”
I guess when something works well, it doesn’t cause gratefulness but creates the expectation that it works perfectly 🤷♂️