https://pulumi.com logo
#python
Title
# python
g

glamorous-forest-5773

01/27/2022, 9:20 AM
Hi all, is there a proper guide on how to use
pulumi.input_type
decorator to define internal datatypes. I'm trying to use Pydantic + pulumi.input_type decorator to create schemas with validation + the ability to resolve nested Output attributes. But it looks like, the decorator is tampering the attributes which results in some weird behavior for pydantic models.
g

great-queen-39697

01/27/2022, 3:48 PM
I'm not aware of a specific guide, but I also don't see this content in the docs, so perhaps the design doc that's embedded in the SDK might help? https://github.com/pulumi/pulumi/blob/master/sdk/python/lib/pulumi/_types.py#L15-L266
It has a bunch of examples
g

great-sunset-355

01/31/2022, 10:16 AM
I'm using pydantic as well and I do not think you'll be able to resolve the Ouput because it's being executed in an async io event loop that you do not have access to from your pulumi code. So you'll have to rely on dicts (maybe typed dicts to the rescue). - This problem goes partially away in TypeScript where pulumi works with interfaces. Please let me know if you find a good solution for this. Because having to remember the structure is painful. Otherwise I just do this:
Copy code
from typing import Sequence, TypeVar, Union
from pydantic import BaseModel
import pulumi


T = TypeVar("T")
PulumiSequenceInputLike = Union[Sequence[T], pulumi.Output[T]]
PulumiInputLike = Union[T, pulumi.Output[T]]

class AutoScalingArgs(BaseModel):
    """Fargate autoscaling arguments."""

    memory_target_value: PulumiInputLike[int] = 60
    """Scale up when memory usage  exceeds the value [%]."""
    cpu_target_value: PulumiInputLike[int] = 60
    """Scale up when CPU usage  exceeds the value [%]."""
    max_tasks: PulumiInputLike[int] = 4
    min_tasks: PulumiInputLike[int] = 1
    desired_count: PulumiInputLike[int] = 1

    class Config:
        arbitrary_types_allowed = True
g

glamorous-forest-5773

02/22/2022, 11:41 AM
@great-sunset-355 did you find a solution? The
pulumi.input_type
decorator is messing up the pydantic attributes
which causes default values to not work
g

great-sunset-355

02/22/2022, 11:45 AM
Do you have any code with the problem? Simply is not possible to specify
Input
type, you need to use
Output
as a type
g

glamorous-forest-5773

02/22/2022, 11:46 AM
you can use input type, and I manage to get it to unwrap nested Input/Output attributes
Copy code
@pulumi.runtime.test
def test_person_with_default():
    from pydantic import BaseModel
    from typing import TypeVar, Union, Optional

    T = TypeVar("T")
    Input = Union[T, pulumi.Output[T]]

    class PulumiBaseModel(BaseModel):
        class Config:
            arbitrary_types_allowed = True

    @pulumi.input_type
    class Person(PulumiBaseModel):
        name: Optional[Input[str]] = "John Doe"

    a = Person()

    def check(a):
        assert a.name == "John Doe"

    return pulumi.Output.from_input(a).apply(check)
but the decorator breaks the default value in the pydantic model
Copy code
test_person_with_default Failed: [undefined]TypeError: __create_fn__.<locals>.__init__() missing 1 required keyword-only argument: 'name'
removing the decorator fixes this, but I can no longer easily unwrap nested outputs
g

great-sunset-355

02/22/2022, 2:21 PM
Did you try to use post init or ovrride the init? There are some docs about it in pydantic. Else check issues/discussions. Another option is to drop pydantic and try dataclasses or attrs
g

glamorous-forest-5773

02/23/2022, 7:14 AM
I've cracked it! 😄
94 Views