Repository: strawberry-graphql/strawberry

Issue:
Mypy complains wrongly about to_pydantic when using a pydantic type that was converted with all_fields=True
<!-- Provide a general summary of the bug in the title above. -->

<!--- This template is entirely optional and can be removed, but is here to help both you and us. -->
<!--- Anything on lines wrapped in comments like these will not show up in the final text. -->

## Describe the Bug

I introduced this bug in [0.118.0](https://github.com/strawberry-graphql/strawberry/commit/c80744570f2bf13404c92af1faf8891b2952e121)

```
class MyModel(BaseModel):
    item: str


@strawberry_from_pydantic(model=MyModel, all_fields=True
)
class StrawberryModel:
    ...

StrawberryModel(item).to_pydantic()
# mypy errors incorrectly
```

I should be able to fix it by infering that all_fields=True if there are no strawberry.auto declarations in the class

## System Information

 - Operating system:
 - Strawberry version (if applicable):

## Additional Context

<!-- Add any other relevant information about the problem here. -->



Discussion:

Resolving patch:
diff --git a/strawberry/ext/mypy_plugin.py b/strawberry/ext/mypy_plugin.py
--- a/strawberry/ext/mypy_plugin.py
+++ b/strawberry/ext/mypy_plugin.py
@@ -424,28 +424,39 @@ def strawberry_pydantic_class_callback(ctx: ClassDefContext) -> None:
                 ctx.reason,
             )
 
-        missing_pydantic_fields: Set["PydanticModelField"] = set(
+        potentially_missing_fields: Set["PydanticModelField"] = set(
             f for f in pydantic_fields if f.name not in new_strawberry_fields
         )
 
-        # Add to_pydantic
-        # TODO: Only add this if not manually defined
-        add_method(
-            ctx,
-            "to_pydantic",
-            args=[
-                f.to_argument(
-                    # TODO: use_alias should depend on config?
-                    info=model_type.type,
-                    typed=True,
-                    force_optional=False,
-                    use_alias=True,
-                )
-                for f in missing_pydantic_fields
-            ],
-            return_type=model_type,
+        """
+        Need to check if all_fields=True from the pydantic decorator
+        There is no way to real check that Literal[True] was used
+        We just check if the strawberry type is missing all the fields
+        This means that the user is using all_fields=True
+        """
+        is_all_fields: bool = len(potentially_missing_fields) == len(pydantic_fields)
+        missing_pydantic_fields: Set["PydanticModelField"] = (
+            potentially_missing_fields if not is_all_fields else set()
         )
 
+        # Add the default to_pydantic if undefined by the user
+        if "to_pydantic" not in ctx.cls.info.names:
+            add_method(
+                ctx,
+                "to_pydantic",
+                args=[
+                    f.to_argument(
+                        # TODO: use_alias should depend on config?
+                        info=model_type.type,
+                        typed=True,
+                        force_optional=False,
+                        use_alias=True,
+                    )
+                    for f in missing_pydantic_fields
+                ],
+                return_type=model_type,
+            )
+
         # Add from_pydantic
         model_argument = Argument(
             variable=Var(name="instance", type=model_type),


Test patch:
diff --git a/tests/mypy/test_pydantic.decorators.yml b/tests/mypy/test_pydantic.decorators.yml
--- a/tests/mypy/test_pydantic.decorators.yml
+++ b/tests/mypy/test_pydantic.decorators.yml
@@ -204,3 +204,84 @@
 
     MyModelStrawberry(email="").to_pydantic()
   out: |
+- case: test_to_pydantic_kwargs_with_all_fields
+  main: |
+    from pydantic import BaseModel
+    from typing import Optional
+    import strawberry
+
+
+    class MyModel(BaseModel):
+        email: str
+        password: Optional[str]
+
+
+    @strawberry.experimental.pydantic.input(model=MyModel, all_fields=True)
+    class MyModelStrawberry:
+        ...
+
+
+    MyModelStrawberry(email="").to_pydantic()
+  out: |
+- case: test_to_pydantic_kwargs_with_all_fields_adding_field
+  main: |
+    from pydantic import BaseModel
+    from typing import Optional
+    import strawberry
+
+
+    class MyModel(BaseModel):
+        email: str
+        password: Optional[str]
+
+        @property
+        def age(self) -> int:
+            return 42
+
+
+    @strawberry.experimental.pydantic.input(model=MyModel, all_fields=True)
+    class MyModelStrawberry:
+        age: int # read from the property
+
+
+    MyModelStrawberry(email="").to_pydantic()
+  out: |
+- case: test_to_pydantic_kwargs_private_field
+  main: |
+    from pydantic import BaseModel
+    from typing import Optional
+    import strawberry
+
+
+    class MyModel(BaseModel):
+        email: str
+        _age: int # for pydantic, underscore means private field
+
+
+    @strawberry.experimental.pydantic.input(model=MyModel)
+    class MyModelStrawberry:
+        email: strawberry.auto
+
+
+    MyModelStrawberry(email="").to_pydantic()
+  out: |
+- case: test_to_pydantic_custom
+  main: |
+    from pydantic import BaseModel
+    import strawberry
+
+    class MyModel(BaseModel):
+        email: str
+
+    @strawberry.experimental.pydantic.input(model=MyModel)
+    class MyModelStrawberry:
+        email: strawberry.auto
+
+        def to_pydantic(self, another_param: str):
+            # custom to_pydantic overwrites default params
+            ...
+
+    MyModelStrawberry(email="").to_pydantic()
+
+  out: |
+    main:15: error: Missing positional argument "another_param" in call to "to_pydantic" of "MyModelStrawberry"  [call-arg]