strawberry icon indicating copy to clipboard operation
strawberry copied to clipboard

`SomeType.from_pydantic(...)` does not call resolvers of underlying types

Open benzolium opened this issue 1 year ago • 2 comments

SomeType.from_pydantic(...) does not call resolvers of underlying types.

Or probably I'm doing something wrong. 😄

Describe the Bug

It's better explained as a test:

def test_from_pydantic_calls_underlying_resolvers():
    class UserName(BaseModel):
        first_name: str
        last_name: str

    @strawberry.experimental.pydantic.type(UserName)
    class UserNameType:
        last_name: strawberry.auto

        @strawberry.field
        def first_name(
            self,
            root: UserName,
        ) -> str:
            return f"updated {root.first_name}"


    class User(BaseModel):
        age: int
        name: str


    @strawberry.experimental.pydantic.type(User)
    class UserType:
        age: strawberry.auto

        @strawberry.field
        def name(
            self,
            root: User,
        ) -> UserNameType:
            first_name, last_name = root.name.split(" ")
            return UserNameType.from_pydantic(  # <- here's the thing
                UserName(first_name=first_name, last_name=last_name)
            )

    origin_user = User(age=1, name="John Doe")
    user = UserType.from_pydantic(origin_user)

    assert user.age == 1
    assert user.name(origin_user).first_name == "John"

Yells:

E       AssertionError: assert <bound method test_something.<locals>.UserNameType.first_name of UserNameType(last_name='Doe')> == 'John'
E        +  where <bound method test_something.<locals>.UserNameType.first_name of UserNameType(last_name='Doe')> = UserNameType(last_name='Doe').first_name
E        +    where UserNameType(last_name='Doe') = <bound method test_something.<locals>.UserType.name of UserType(age=1)>(User(age=1, name='John Doe'))
E        +      where <bound method test_something.<locals>.UserType.name of UserType(age=1)> = UserType(age=1).name

However this piece of code works as expected:

@strawberry.experimental.pydantic.type(User)
class UserType:
    age: strawberry.auto

    @strawberry.field
    def name(
        self,
        root: User,
    ) -> UserNameType:
        first_name, last_name = root.name.split(" ")
        # <- note pydantic type is returned instead of `UserType.from_pydantic`
        return UserName(first_name=first_name, last_name=last_name)

System Information

  • Operating system: mac os
  • Strawberry version (if applicable): 0.124.0

benzolium avatar Aug 10 '22 12:08 benzolium

so the error is saying that first_name is a method instead of a string, because, we defined that as a method in

    @strawberry.experimental.pydantic.type(UserName)
    class UserNameType:
        last_name: strawberry.auto

        @strawberry.field
        def first_name(
            self,
            root: UserName,
        ) -> str:
            return f"updated {root.first_name}"

is your expected behaviour such that first_name gets automatically evaluated to become a string?

thejaminator avatar Aug 10 '22 17:08 thejaminator

@thejaminator idk. Docs are quite confusing.

If I return pydantic type in resolver, everything works fine - first_name is called automatically. Butmypy complains that I'm returning UserName instead of UserNameType.

However if I return UserNameType.from_pydantic(UserName(...)), first_name is not called, but mypy check is ok.

benzolium avatar Aug 11 '22 05:08 benzolium