We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Interface values don't convert correctly from Pydantic models
When calling `from_pydantic` on a class with an interface field, the field value is always converted into an instance of the base class, no matter what its starting type is. The expected behavior should probably be to convert to the corresponding subtype class instead. See here for an example: https://gist.github.com/Matt343/fbce0cdffe1523bb22016bed6f65473f

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `strawberry/experimental/pydantic/__init__.py`
Content:
```
1 from .error_type import error_type
2 from .exceptions import UnregisteredTypeException
3 from .object_type import input, type
4 
5 
6 __all__ = ["error_type", "UnregisteredTypeException", "input", "type"]
7
```

Path: `strawberry/experimental/pydantic/conversion.py`
Content:
```
1 from typing import Union, cast
2 
3 from strawberry.field import StrawberryField
4 from strawberry.scalars import is_scalar
5 from strawberry.type import StrawberryList, StrawberryOptional, StrawberryType
6 from strawberry.union import StrawberryUnion
7 
8 
9 def _convert_from_pydantic_to_strawberry_type(
10     type_: Union[StrawberryType, type], data_from_model=None, extra=None
11 ):
12     data = data_from_model if data_from_model is not None else extra
13 
14     if isinstance(type_, StrawberryOptional):
15         if data is None:
16             return data
17         return _convert_from_pydantic_to_strawberry_type(
18             type_.of_type, data_from_model=data, extra=extra
19         )
20     if isinstance(type_, StrawberryUnion):
21         for option_type in type_.types:
22             if hasattr(option_type, "_pydantic_type"):
23                 source_type = option_type._pydantic_type  # type: ignore
24             else:
25                 source_type = cast(type, option_type)
26             if isinstance(data, source_type):
27                 return _convert_from_pydantic_to_strawberry_type(
28                     option_type, data_from_model=data, extra=extra
29                 )
30     if isinstance(type_, StrawberryList):
31         items = []
32         for index, item in enumerate(data):
33             items.append(
34                 _convert_from_pydantic_to_strawberry_type(
35                     type_.of_type,
36                     data_from_model=item,
37                     extra=extra[index] if extra else None,
38                 )
39             )
40 
41         return items
42     elif is_scalar(type_):
43         return data
44     else:
45         return convert_pydantic_model_to_strawberry_class(
46             type_, model_instance=data_from_model, extra=extra
47         )
48 
49 
50 def convert_pydantic_model_to_strawberry_class(cls, *, model_instance=None, extra=None):
51     extra = extra or {}
52     kwargs = {}
53 
54     for field in cls._type_definition.fields:
55         field = cast(StrawberryField, field)
56         python_name = field.python_name
57 
58         data_from_extra = extra.get(python_name, None)
59         data_from_model = (
60             getattr(model_instance, python_name, None) if model_instance else None
61         )
62         kwargs[python_name] = _convert_from_pydantic_to_strawberry_type(
63             field.type, data_from_model, extra=data_from_extra
64         )
65 
66     return cls(**kwargs)
67
```

Path: `strawberry/experimental/pydantic/object_type.py`
Content:
```
1 import builtins
2 import dataclasses
3 from functools import partial
4 from typing import Any, Dict, List, Optional, Tuple, Type, cast
5 
6 from pydantic import BaseModel
7 from pydantic.fields import ModelField
8 
9 from strawberry.arguments import UNSET
10 from strawberry.experimental.pydantic.conversion import (
11     convert_pydantic_model_to_strawberry_class,
12 )
13 from strawberry.experimental.pydantic.fields import get_basic_type
14 from strawberry.field import StrawberryField
15 from strawberry.object_type import _process_type, _wrap_dataclass
16 from strawberry.private import Private
17 from strawberry.types.type_resolver import _get_fields
18 from strawberry.types.types import FederationTypeParams, TypeDefinition
19 
20 from .exceptions import MissingFieldsListError, UnregisteredTypeException
21 
22 
23 def replace_pydantic_types(type_: Any):
24     if hasattr(type_, "__args__"):
25         new_type = type_.copy_with(
26             tuple(replace_pydantic_types(t) for t in type_.__args__)
27         )
28 
29         if isinstance(new_type, TypeDefinition):
30             # TODO: Not sure if this is necessary. No coverage in tests
31             # TODO: Unnecessary with StrawberryObject
32 
33             new_type = builtins.type(
34                 new_type.name,
35                 (),
36                 {"_type_definition": new_type},
37             )
38 
39         return new_type
40 
41     if issubclass(type_, BaseModel):
42         if hasattr(type_, "_strawberry_type"):
43             return type_._strawberry_type
44         else:
45             raise UnregisteredTypeException(type_)
46 
47     return type_
48 
49 
50 def get_type_for_field(field: ModelField):
51     type_ = field.outer_type_
52     type_ = get_basic_type(type_)
53     type_ = replace_pydantic_types(type_)
54 
55     if not field.required:
56         type_ = Optional[type_]
57 
58     return type_
59 
60 
61 def _get_private_fields(cls: Type) -> List[dataclasses.Field]:
62     private_fields: List[dataclasses.Field] = []
63     for field in dataclasses.fields(cls):
64         if isinstance(field.type, Private):
65             private_fields.append(field)
66     return private_fields
67 
68 
69 def type(
70     model: Type[BaseModel],
71     *,
72     fields: List[str],
73     name: Optional[str] = None,
74     is_input: bool = False,
75     is_interface: bool = False,
76     description: Optional[str] = None,
77     federation: Optional[FederationTypeParams] = None,
78 ):
79     def wrap(cls):
80         if not fields:
81             raise MissingFieldsListError(model)
82 
83         model_fields = model.__fields__
84         fields_set = set(fields)
85 
86         all_fields: List[Tuple[str, Any, dataclasses.Field]] = [
87             (
88                 name,
89                 get_type_for_field(field),
90                 StrawberryField(
91                     python_name=field.name,
92                     graphql_name=field.alias if field.has_alias else None,
93                     default=field.default if not field.required else UNSET,
94                     default_factory=(
95                         field.default_factory if field.default_factory else UNSET
96                     ),
97                     type_annotation=get_type_for_field(field),
98                 ),
99             )
100             for name, field in model_fields.items()
101             if name in fields_set
102         ]
103 
104         wrapped = _wrap_dataclass(cls)
105         extra_fields = cast(List[dataclasses.Field], _get_fields(wrapped))
106         private_fields = _get_private_fields(wrapped)
107 
108         all_fields.extend(
109             (
110                 (
111                     field.name,
112                     field.type,
113                     field,
114                 )
115                 for field in extra_fields + private_fields
116             )
117         )
118 
119         # Sort fields so that fields with missing defaults go first
120         # because dataclasses require that fields with no defaults are defined
121         # first
122         missing_default = []
123         has_default = []
124         for field in all_fields:
125             if field[2].default is dataclasses.MISSING:
126                 missing_default.append(field)
127             else:
128                 has_default.append(field)
129 
130         sorted_fields = missing_default + has_default
131 
132         cls = dataclasses.make_dataclass(
133             cls.__name__,
134             sorted_fields,
135         )
136 
137         _process_type(
138             cls,
139             name=name,
140             is_input=is_input,
141             is_interface=is_interface,
142             description=description,
143             federation=federation,
144         )
145 
146         model._strawberry_type = cls  # type: ignore
147         cls._pydantic_type = model  # type: ignore
148 
149         def from_pydantic(instance: Any, extra: Dict[str, Any] = None) -> Any:
150             return convert_pydantic_model_to_strawberry_class(
151                 cls=cls, model_instance=instance, extra=extra
152             )
153 
154         def to_pydantic(self) -> Any:
155             instance_kwargs = dataclasses.asdict(self)
156 
157             return model(**instance_kwargs)
158 
159         cls.from_pydantic = staticmethod(from_pydantic)
160         cls.to_pydantic = to_pydantic
161 
162         return cls
163 
164     return wrap
165 
166 
167 input = partial(type, is_input=True)
168
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/strawberry/experimental/pydantic/__init__.py b/strawberry/experimental/pydantic/__init__.py
--- a/strawberry/experimental/pydantic/__init__.py
+++ b/strawberry/experimental/pydantic/__init__.py
@@ -1,6 +1,6 @@
 from .error_type import error_type
 from .exceptions import UnregisteredTypeException
-from .object_type import input, type
+from .object_type import input, interface, type
 
 
-__all__ = ["error_type", "UnregisteredTypeException", "input", "type"]
+__all__ = ["error_type", "UnregisteredTypeException", "input", "type", "interface"]
diff --git a/strawberry/experimental/pydantic/conversion.py b/strawberry/experimental/pydantic/conversion.py
--- a/strawberry/experimental/pydantic/conversion.py
+++ b/strawberry/experimental/pydantic/conversion.py
@@ -1,5 +1,6 @@
 from typing import Union, cast
 
+from strawberry.enum import EnumDefinition
 from strawberry.field import StrawberryField
 from strawberry.scalars import is_scalar
 from strawberry.type import StrawberryList, StrawberryOptional, StrawberryType
@@ -27,6 +28,8 @@
                 return _convert_from_pydantic_to_strawberry_type(
                     option_type, data_from_model=data, extra=extra
                 )
+    if isinstance(type_, EnumDefinition):
+        return data
     if isinstance(type_, StrawberryList):
         items = []
         for index, item in enumerate(data):
@@ -42,6 +45,10 @@
     elif is_scalar(type_):
         return data
     else:
+        # in the case of an interface, the concrete type may be more specific
+        # than the type in the field definition
+        if hasattr(type(data), "_strawberry_type"):
+            type_ = type(data)._strawberry_type
         return convert_pydantic_model_to_strawberry_class(
             type_, model_instance=data_from_model, extra=extra
         )
diff --git a/strawberry/experimental/pydantic/object_type.py b/strawberry/experimental/pydantic/object_type.py
--- a/strawberry/experimental/pydantic/object_type.py
+++ b/strawberry/experimental/pydantic/object_type.py
@@ -132,6 +132,7 @@
         cls = dataclasses.make_dataclass(
             cls.__name__,
             sorted_fields,
+            bases=cls.__bases__,
         )
 
         _process_type(
@@ -165,3 +166,5 @@
 
 
 input = partial(type, is_input=True)
+
+interface = partial(type, is_interface=True)

{"golden_diff": "diff --git a/strawberry/experimental/pydantic/__init__.py b/strawberry/experimental/pydantic/__init__.py\n--- a/strawberry/experimental/pydantic/__init__.py\n+++ b/strawberry/experimental/pydantic/__init__.py\n@@ -1,6 +1,6 @@\n from .error_type import error_type\n from .exceptions import UnregisteredTypeException\n-from .object_type import input, type\n+from .object_type import input, interface, type\n \n \n-__all__ = [\"error_type\", \"UnregisteredTypeException\", \"input\", \"type\"]\n+__all__ = [\"error_type\", \"UnregisteredTypeException\", \"input\", \"type\", \"interface\"]\ndiff --git a/strawberry/experimental/pydantic/conversion.py b/strawberry/experimental/pydantic/conversion.py\n--- a/strawberry/experimental/pydantic/conversion.py\n+++ b/strawberry/experimental/pydantic/conversion.py\n@@ -1,5 +1,6 @@\n from typing import Union, cast\n \n+from strawberry.enum import EnumDefinition\n from strawberry.field import StrawberryField\n from strawberry.scalars import is_scalar\n from strawberry.type import StrawberryList, StrawberryOptional, StrawberryType\n@@ -27,6 +28,8 @@\n                 return _convert_from_pydantic_to_strawberry_type(\n                     option_type, data_from_model=data, extra=extra\n                 )\n+    if isinstance(type_, EnumDefinition):\n+        return data\n     if isinstance(type_, StrawberryList):\n         items = []\n         for index, item in enumerate(data):\n@@ -42,6 +45,10 @@\n     elif is_scalar(type_):\n         return data\n     else:\n+        # in the case of an interface, the concrete type may be more specific\n+        # than the type in the field definition\n+        if hasattr(type(data), \"_strawberry_type\"):\n+            type_ = type(data)._strawberry_type\n         return convert_pydantic_model_to_strawberry_class(\n             type_, model_instance=data_from_model, extra=extra\n         )\ndiff --git a/strawberry/experimental/pydantic/object_type.py b/strawberry/experimental/pydantic/object_type.py\n--- a/strawberry/experimental/pydantic/object_type.py\n+++ b/strawberry/experimental/pydantic/object_type.py\n@@ -132,6 +132,7 @@\n         cls = dataclasses.make_dataclass(\n             cls.__name__,\n             sorted_fields,\n+            bases=cls.__bases__,\n         )\n \n         _process_type(\n@@ -165,3 +166,5 @@\n \n \n input = partial(type, is_input=True)\n+\n+interface = partial(type, is_interface=True)\n", "issue": "Interface values don't convert correctly from Pydantic models\nWhen calling `from_pydantic` on a class with an interface field, the field value is always converted into an instance of the base class, no matter what its starting type is. The expected behavior should probably be to convert to the corresponding subtype class instead. See here for an example: https://gist.github.com/Matt343/fbce0cdffe1523bb22016bed6f65473f\n", "before_files": [{"content": "from .error_type import error_type\nfrom .exceptions import UnregisteredTypeException\nfrom .object_type import input, type\n\n\n__all__ = [\"error_type\", \"UnregisteredTypeException\", \"input\", \"type\"]\n", "path": "strawberry/experimental/pydantic/__init__.py"}, {"content": "from typing import Union, cast\n\nfrom strawberry.field import StrawberryField\nfrom strawberry.scalars import is_scalar\nfrom strawberry.type import StrawberryList, StrawberryOptional, StrawberryType\nfrom strawberry.union import StrawberryUnion\n\n\ndef _convert_from_pydantic_to_strawberry_type(\n    type_: Union[StrawberryType, type], data_from_model=None, extra=None\n):\n    data = data_from_model if data_from_model is not None else extra\n\n    if isinstance(type_, StrawberryOptional):\n        if data is None:\n            return data\n        return _convert_from_pydantic_to_strawberry_type(\n            type_.of_type, data_from_model=data, extra=extra\n        )\n    if isinstance(type_, StrawberryUnion):\n        for option_type in type_.types:\n            if hasattr(option_type, \"_pydantic_type\"):\n                source_type = option_type._pydantic_type  # type: ignore\n            else:\n                source_type = cast(type, option_type)\n            if isinstance(data, source_type):\n                return _convert_from_pydantic_to_strawberry_type(\n                    option_type, data_from_model=data, extra=extra\n                )\n    if isinstance(type_, StrawberryList):\n        items = []\n        for index, item in enumerate(data):\n            items.append(\n                _convert_from_pydantic_to_strawberry_type(\n                    type_.of_type,\n                    data_from_model=item,\n                    extra=extra[index] if extra else None,\n                )\n            )\n\n        return items\n    elif is_scalar(type_):\n        return data\n    else:\n        return convert_pydantic_model_to_strawberry_class(\n            type_, model_instance=data_from_model, extra=extra\n        )\n\n\ndef convert_pydantic_model_to_strawberry_class(cls, *, model_instance=None, extra=None):\n    extra = extra or {}\n    kwargs = {}\n\n    for field in cls._type_definition.fields:\n        field = cast(StrawberryField, field)\n        python_name = field.python_name\n\n        data_from_extra = extra.get(python_name, None)\n        data_from_model = (\n            getattr(model_instance, python_name, None) if model_instance else None\n        )\n        kwargs[python_name] = _convert_from_pydantic_to_strawberry_type(\n            field.type, data_from_model, extra=data_from_extra\n        )\n\n    return cls(**kwargs)\n", "path": "strawberry/experimental/pydantic/conversion.py"}, {"content": "import builtins\nimport dataclasses\nfrom functools import partial\nfrom typing import Any, Dict, List, Optional, Tuple, Type, cast\n\nfrom pydantic import BaseModel\nfrom pydantic.fields import ModelField\n\nfrom strawberry.arguments import UNSET\nfrom strawberry.experimental.pydantic.conversion import (\n    convert_pydantic_model_to_strawberry_class,\n)\nfrom strawberry.experimental.pydantic.fields import get_basic_type\nfrom strawberry.field import StrawberryField\nfrom strawberry.object_type import _process_type, _wrap_dataclass\nfrom strawberry.private import Private\nfrom strawberry.types.type_resolver import _get_fields\nfrom strawberry.types.types import FederationTypeParams, TypeDefinition\n\nfrom .exceptions import MissingFieldsListError, UnregisteredTypeException\n\n\ndef replace_pydantic_types(type_: Any):\n    if hasattr(type_, \"__args__\"):\n        new_type = type_.copy_with(\n            tuple(replace_pydantic_types(t) for t in type_.__args__)\n        )\n\n        if isinstance(new_type, TypeDefinition):\n            # TODO: Not sure if this is necessary. No coverage in tests\n            # TODO: Unnecessary with StrawberryObject\n\n            new_type = builtins.type(\n                new_type.name,\n                (),\n                {\"_type_definition\": new_type},\n            )\n\n        return new_type\n\n    if issubclass(type_, BaseModel):\n        if hasattr(type_, \"_strawberry_type\"):\n            return type_._strawberry_type\n        else:\n            raise UnregisteredTypeException(type_)\n\n    return type_\n\n\ndef get_type_for_field(field: ModelField):\n    type_ = field.outer_type_\n    type_ = get_basic_type(type_)\n    type_ = replace_pydantic_types(type_)\n\n    if not field.required:\n        type_ = Optional[type_]\n\n    return type_\n\n\ndef _get_private_fields(cls: Type) -> List[dataclasses.Field]:\n    private_fields: List[dataclasses.Field] = []\n    for field in dataclasses.fields(cls):\n        if isinstance(field.type, Private):\n            private_fields.append(field)\n    return private_fields\n\n\ndef type(\n    model: Type[BaseModel],\n    *,\n    fields: List[str],\n    name: Optional[str] = None,\n    is_input: bool = False,\n    is_interface: bool = False,\n    description: Optional[str] = None,\n    federation: Optional[FederationTypeParams] = None,\n):\n    def wrap(cls):\n        if not fields:\n            raise MissingFieldsListError(model)\n\n        model_fields = model.__fields__\n        fields_set = set(fields)\n\n        all_fields: List[Tuple[str, Any, dataclasses.Field]] = [\n            (\n                name,\n                get_type_for_field(field),\n                StrawberryField(\n                    python_name=field.name,\n                    graphql_name=field.alias if field.has_alias else None,\n                    default=field.default if not field.required else UNSET,\n                    default_factory=(\n                        field.default_factory if field.default_factory else UNSET\n                    ),\n                    type_annotation=get_type_for_field(field),\n                ),\n            )\n            for name, field in model_fields.items()\n            if name in fields_set\n        ]\n\n        wrapped = _wrap_dataclass(cls)\n        extra_fields = cast(List[dataclasses.Field], _get_fields(wrapped))\n        private_fields = _get_private_fields(wrapped)\n\n        all_fields.extend(\n            (\n                (\n                    field.name,\n                    field.type,\n                    field,\n                )\n                for field in extra_fields + private_fields\n            )\n        )\n\n        # Sort fields so that fields with missing defaults go first\n        # because dataclasses require that fields with no defaults are defined\n        # first\n        missing_default = []\n        has_default = []\n        for field in all_fields:\n            if field[2].default is dataclasses.MISSING:\n                missing_default.append(field)\n            else:\n                has_default.append(field)\n\n        sorted_fields = missing_default + has_default\n\n        cls = dataclasses.make_dataclass(\n            cls.__name__,\n            sorted_fields,\n        )\n\n        _process_type(\n            cls,\n            name=name,\n            is_input=is_input,\n            is_interface=is_interface,\n            description=description,\n            federation=federation,\n        )\n\n        model._strawberry_type = cls  # type: ignore\n        cls._pydantic_type = model  # type: ignore\n\n        def from_pydantic(instance: Any, extra: Dict[str, Any] = None) -> Any:\n            return convert_pydantic_model_to_strawberry_class(\n                cls=cls, model_instance=instance, extra=extra\n            )\n\n        def to_pydantic(self) -> Any:\n            instance_kwargs = dataclasses.asdict(self)\n\n            return model(**instance_kwargs)\n\n        cls.from_pydantic = staticmethod(from_pydantic)\n        cls.to_pydantic = to_pydantic\n\n        return cls\n\n    return wrap\n\n\ninput = partial(type, is_input=True)\n", "path": "strawberry/experimental/pydantic/object_type.py"}], "after_files": [{"content": "from .error_type import error_type\nfrom .exceptions import UnregisteredTypeException\nfrom .object_type import input, interface, type\n\n\n__all__ = [\"error_type\", \"UnregisteredTypeException\", \"input\", \"type\", \"interface\"]\n", "path": "strawberry/experimental/pydantic/__init__.py"}, {"content": "from typing import Union, cast\n\nfrom strawberry.enum import EnumDefinition\nfrom strawberry.field import StrawberryField\nfrom strawberry.scalars import is_scalar\nfrom strawberry.type import StrawberryList, StrawberryOptional, StrawberryType\nfrom strawberry.union import StrawberryUnion\n\n\ndef _convert_from_pydantic_to_strawberry_type(\n    type_: Union[StrawberryType, type], data_from_model=None, extra=None\n):\n    data = data_from_model if data_from_model is not None else extra\n\n    if isinstance(type_, StrawberryOptional):\n        if data is None:\n            return data\n        return _convert_from_pydantic_to_strawberry_type(\n            type_.of_type, data_from_model=data, extra=extra\n        )\n    if isinstance(type_, StrawberryUnion):\n        for option_type in type_.types:\n            if hasattr(option_type, \"_pydantic_type\"):\n                source_type = option_type._pydantic_type  # type: ignore\n            else:\n                source_type = cast(type, option_type)\n            if isinstance(data, source_type):\n                return _convert_from_pydantic_to_strawberry_type(\n                    option_type, data_from_model=data, extra=extra\n                )\n    if isinstance(type_, EnumDefinition):\n        return data\n    if isinstance(type_, StrawberryList):\n        items = []\n        for index, item in enumerate(data):\n            items.append(\n                _convert_from_pydantic_to_strawberry_type(\n                    type_.of_type,\n                    data_from_model=item,\n                    extra=extra[index] if extra else None,\n                )\n            )\n\n        return items\n    elif is_scalar(type_):\n        return data\n    else:\n        # in the case of an interface, the concrete type may be more specific\n        # than the type in the field definition\n        if hasattr(type(data), \"_strawberry_type\"):\n            type_ = type(data)._strawberry_type\n        return convert_pydantic_model_to_strawberry_class(\n            type_, model_instance=data_from_model, extra=extra\n        )\n\n\ndef convert_pydantic_model_to_strawberry_class(cls, *, model_instance=None, extra=None):\n    extra = extra or {}\n    kwargs = {}\n\n    for field in cls._type_definition.fields:\n        field = cast(StrawberryField, field)\n        python_name = field.python_name\n\n        data_from_extra = extra.get(python_name, None)\n        data_from_model = (\n            getattr(model_instance, python_name, None) if model_instance else None\n        )\n        kwargs[python_name] = _convert_from_pydantic_to_strawberry_type(\n            field.type, data_from_model, extra=data_from_extra\n        )\n\n    return cls(**kwargs)\n", "path": "strawberry/experimental/pydantic/conversion.py"}, {"content": "import builtins\nimport dataclasses\nfrom functools import partial\nfrom typing import Any, Dict, List, Optional, Tuple, Type, cast\n\nfrom pydantic import BaseModel\nfrom pydantic.fields import ModelField\n\nfrom strawberry.arguments import UNSET\nfrom strawberry.experimental.pydantic.conversion import (\n    convert_pydantic_model_to_strawberry_class,\n)\nfrom strawberry.experimental.pydantic.fields import get_basic_type\nfrom strawberry.field import StrawberryField\nfrom strawberry.object_type import _process_type, _wrap_dataclass\nfrom strawberry.private import Private\nfrom strawberry.types.type_resolver import _get_fields\nfrom strawberry.types.types import FederationTypeParams, TypeDefinition\n\nfrom .exceptions import MissingFieldsListError, UnregisteredTypeException\n\n\ndef replace_pydantic_types(type_: Any):\n    if hasattr(type_, \"__args__\"):\n        new_type = type_.copy_with(\n            tuple(replace_pydantic_types(t) for t in type_.__args__)\n        )\n\n        if isinstance(new_type, TypeDefinition):\n            # TODO: Not sure if this is necessary. No coverage in tests\n            # TODO: Unnecessary with StrawberryObject\n\n            new_type = builtins.type(\n                new_type.name,\n                (),\n                {\"_type_definition\": new_type},\n            )\n\n        return new_type\n\n    if issubclass(type_, BaseModel):\n        if hasattr(type_, \"_strawberry_type\"):\n            return type_._strawberry_type\n        else:\n            raise UnregisteredTypeException(type_)\n\n    return type_\n\n\ndef get_type_for_field(field: ModelField):\n    type_ = field.outer_type_\n    type_ = get_basic_type(type_)\n    type_ = replace_pydantic_types(type_)\n\n    if not field.required:\n        type_ = Optional[type_]\n\n    return type_\n\n\ndef _get_private_fields(cls: Type) -> List[dataclasses.Field]:\n    private_fields: List[dataclasses.Field] = []\n    for field in dataclasses.fields(cls):\n        if isinstance(field.type, Private):\n            private_fields.append(field)\n    return private_fields\n\n\ndef type(\n    model: Type[BaseModel],\n    *,\n    fields: List[str],\n    name: Optional[str] = None,\n    is_input: bool = False,\n    is_interface: bool = False,\n    description: Optional[str] = None,\n    federation: Optional[FederationTypeParams] = None,\n):\n    def wrap(cls):\n        if not fields:\n            raise MissingFieldsListError(model)\n\n        model_fields = model.__fields__\n        fields_set = set(fields)\n\n        all_fields: List[Tuple[str, Any, dataclasses.Field]] = [\n            (\n                name,\n                get_type_for_field(field),\n                StrawberryField(\n                    python_name=field.name,\n                    graphql_name=field.alias if field.has_alias else None,\n                    default=field.default if not field.required else UNSET,\n                    default_factory=(\n                        field.default_factory if field.default_factory else UNSET\n                    ),\n                    type_annotation=get_type_for_field(field),\n                ),\n            )\n            for name, field in model_fields.items()\n            if name in fields_set\n        ]\n\n        wrapped = _wrap_dataclass(cls)\n        extra_fields = cast(List[dataclasses.Field], _get_fields(wrapped))\n        private_fields = _get_private_fields(wrapped)\n\n        all_fields.extend(\n            (\n                (\n                    field.name,\n                    field.type,\n                    field,\n                )\n                for field in extra_fields + private_fields\n            )\n        )\n\n        # Sort fields so that fields with missing defaults go first\n        # because dataclasses require that fields with no defaults are defined\n        # first\n        missing_default = []\n        has_default = []\n        for field in all_fields:\n            if field[2].default is dataclasses.MISSING:\n                missing_default.append(field)\n            else:\n                has_default.append(field)\n\n        sorted_fields = missing_default + has_default\n\n        cls = dataclasses.make_dataclass(\n            cls.__name__,\n            sorted_fields,\n            bases=cls.__bases__,\n        )\n\n        _process_type(\n            cls,\n            name=name,\n            is_input=is_input,\n            is_interface=is_interface,\n            description=description,\n            federation=federation,\n        )\n\n        model._strawberry_type = cls  # type: ignore\n        cls._pydantic_type = model  # type: ignore\n\n        def from_pydantic(instance: Any, extra: Dict[str, Any] = None) -> Any:\n            return convert_pydantic_model_to_strawberry_class(\n                cls=cls, model_instance=instance, extra=extra\n            )\n\n        def to_pydantic(self) -> Any:\n            instance_kwargs = dataclasses.asdict(self)\n\n            return model(**instance_kwargs)\n\n        cls.from_pydantic = staticmethod(from_pydantic)\n        cls.to_pydantic = to_pydantic\n\n        return cls\n\n    return wrap\n\n\ninput = partial(type, is_input=True)\n\ninterface = partial(type, is_interface=True)\n", "path": "strawberry/experimental/pydantic/object_type.py"}]}