Is there a clean pattern for dealing with the A x ...
# python
d
Is there a clean pattern for dealing with the A x B grid of union possibilities when you are dealing with Input and Sequence, for example? It seems like, to cover all bases, I have to not only allow for a given field to be
Sequence[Output[str]]
but also
Output[Sequence[str]]
for example. As a follow on, when I want to somehow boil both of these down to some common structure, like doing something like:
Copy code
somevalue: Sequence[Output[str]] | Output[Sequence[str]] = ...
args.something = pulumi.Output.from_input(somevalue).apply(lambda xyx: ....)
Does this end up being an
Output[Sequence[Output[str]]]
or something? Does it just nest forever? Feels like I'm either approaching the typing of my fields wrong or missing some other feature here
👀 1
b
I think the runtime flattens it all to
Output[Sequence[str]]
but don't hold me to that. I'll find someone who can definitively say.
d
My frustration here is mainly around doing typechecking and using validation libraries. I'm totally cool with there being some documented advice that says "Keep the output on the outside and keep it at that". The motivation for my question is mainly as someone making a library to be consumed by others, I can't work out whether it's not fitting with what a user should reasonably expect to only accept a Sequence value if it's wrapped in an output, and not accepting Sequences of Outputs
I'm also wondering how the decision affects Pulumi's ability to generate sensible SDK interfaces when the type on a field has this huge number of types that get combined by the Outputs being plastered all over the place at the different levels
s
I think the runtime flattens it all to
Output[Sequence[str]]
but don't hold me to that. I'll find someone who can definitively say.
I think this is right. Here's a test program to illustrate:
Copy code
# Case 1: a Python list whose elements are Outputs (Sequence[Output[str]])
list_of_outputs: typing.Sequence[pulumi.Output[str]] = [
    pulumi.Output.secret("alpha"),
    pulumi.Output.from_input("beta"),
    pulumi.Output.from_input("gamma"),
]

# Case 2: a single Output that resolves to a Python list (Output[Sequence[str]])
output_of_list: pulumi.Output[typing.Sequence[str]] = pulumi.Output.from_input(
    ["delta", "epsilon", "zeta"]
)

# Normalize both to Output[Sequence[str]]
norm_a: pulumi.Output[typing.Sequence[str]] = pulumi.Output.from_input(list_of_outputs)
norm_b: pulumi.Output[typing.Sequence[str]] = pulumi.Output.from_input(output_of_list)

pulumi.export("norm_a_is_list_of_str", norm_a)
pulumi.export("norm_b_is_list_of_str", norm_b)
Outputs are normalised as expected:
Copy code
"plain,wrapped,foo"
    norm_a_is_list_of_str: [
        [0]: "alpha"
        [1]: "beta"
        [2]: "gamma"
    ]
    norm_b_is_list_of_str: [
        [0]: "delta"
        [1]: "epsilon"
        [2]: "zeta"
    ]
d
Doesn't pass with mypy enabled, though:
Copy code
$ pulumi preview
Enter your passphrase to unlock config/secrets
    (set PULUMI_CONFIG_PASSPHRASE or PULUMI_CONFIG_PASSPHRASE_FILE to remember):  
Enter your passphrase to unlock config/secrets

Previewing update (dev):
     Type                 Name                 Plan     Info
     pulumi:pulumi:Stack  test-stack                    1 error; 2 messages

Diagnostics:
  pulumi:pulumi:Stack (test-stack):
    error: mypy failed: exit status 1

    __main__.py:19: error: Argument 1 to "from_input" of "Output" has incompatible type "Sequence[Output[str]]"; expected "Sequence[str] | Awaitable[Sequence[str]] | Output[Sequence[str]]"  [arg-type]
    Found 1 error in 1 file (checked 1 source file)

Resources:
s
I need to try with mypy 🙂 ... Is there any particular reason to use this instead of pyright? There was a warning last year about pyright being required for use of TypedDict-based inputs because of a performance issue with mypy - see end of this blog post. However, this issue may be partially solved.