We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
new strawberry.lazy not compatible with from __future__ import annotations
# Description

The new way of lazy referencing via strawberry.lazy is not compatible with 
`from __future__ import annotations`

It would be nice to have compatibility as typing.Self is not available for python <=3.10 (the main reason to have `from __future__ import annotations`)

--- 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/utils/typing.py`
Content:
```
1 import ast
2 import sys
3 import typing
4 from collections.abc import AsyncGenerator
5 from functools import lru_cache
6 from typing import (  # type: ignore
7     TYPE_CHECKING,
8     Any,
9     Callable,
10     ClassVar,
11     Dict,
12     ForwardRef,
13     Generic,
14     Optional,
15     Tuple,
16     Type,
17     TypeVar,
18     Union,
19     _eval_type,
20     _GenericAlias,
21     _SpecialForm,
22     cast,
23     overload,
24 )
25 from typing_extensions import Annotated, get_args, get_origin
26 
27 ast_unparse = getattr(ast, "unparse", None)
28 # ast.unparse is only available on python 3.9+. For older versions we will
29 # use `astunparse.unparse`.
30 # We are also using "not TYPE_CHECKING" here because mypy gives an erorr
31 # on tests because "astunparse" is missing stubs, but the mypy action says
32 # that the comment is unused.
33 if not TYPE_CHECKING and ast_unparse is None:
34     import astunparse
35 
36     ast_unparse = astunparse.unparse
37 
38 
39 @lru_cache()
40 def get_generic_alias(type_: Type) -> Type:
41     """Get the generic alias for a type.
42 
43     Given a type, its generic alias from `typing` module will be returned
44     if it exists. For example:
45 
46         >>> get_generic_alias(list)
47         typing.List
48         >>> get_generic_alias(dict)
49         typing.Dict
50 
51     This is mostly useful for python versions prior to 3.9, to get a version
52     of a concrete type which supports `__class_getitem__`. In 3.9+ types like
53     `list`/`dict`/etc are subscriptable and can be used directly instead
54     of their generic alias version.
55     """
56     if isinstance(type_, _SpecialForm):
57         return type_
58 
59     for attr_name in dir(typing):
60         # ignore private attributes, they are not Generic aliases
61         if attr_name.startswith("_"):  # pragma: no cover
62             continue
63 
64         attr = getattr(typing, attr_name)
65         # _GenericAlias overrides all the methods that we can use to know if
66         # this is a subclass of it. But if it has an "_inst" attribute
67         # then it for sure is a _GenericAlias
68         if hasattr(attr, "_inst") and attr.__origin__ is type_:
69             return attr
70 
71     raise AssertionError(f"No GenericAlias available for {type_}")  # pragma: no cover
72 
73 
74 def is_list(annotation: object) -> bool:
75     """Returns True if annotation is a List"""
76 
77     annotation_origin = getattr(annotation, "__origin__", None)
78 
79     return annotation_origin == list
80 
81 
82 def is_union(annotation: object) -> bool:
83     """Returns True if annotation is a Union"""
84 
85     # this check is needed because unions declared with the new syntax `A | B`
86     # don't have a `__origin__` property on them, but they are instances of
87     # `UnionType`, which is only available in Python 3.10+
88     if sys.version_info >= (3, 10):
89         from types import UnionType
90 
91         if isinstance(annotation, UnionType):
92             return True
93 
94     # unions declared as Union[A, B] fall through to this check, even on python 3.10+
95 
96     annotation_origin = getattr(annotation, "__origin__", None)
97 
98     return annotation_origin == Union
99 
100 
101 def is_optional(annotation: Type) -> bool:
102     """Returns True if the annotation is Optional[SomeType]"""
103 
104     # Optionals are represented as unions
105 
106     if not is_union(annotation):
107         return False
108 
109     types = annotation.__args__
110 
111     # A Union to be optional needs to have at least one None type
112     return any(x == None.__class__ for x in types)
113 
114 
115 def get_optional_annotation(annotation: Type) -> Type:
116     types = annotation.__args__
117 
118     non_none_types = tuple(x for x in types if x != None.__class__)
119 
120     # if we have multiple non none types we want to return a copy of this
121     # type (normally a Union type).
122 
123     if len(non_none_types) > 1:
124         return annotation.copy_with(non_none_types)
125 
126     return non_none_types[0]
127 
128 
129 def get_list_annotation(annotation: Type) -> Type:
130     return annotation.__args__[0]
131 
132 
133 def is_concrete_generic(annotation: type) -> bool:
134     ignored_generics = (list, tuple, Union, ClassVar, AsyncGenerator)
135     return (
136         isinstance(annotation, _GenericAlias)
137         and annotation.__origin__ not in ignored_generics
138     )
139 
140 
141 def is_generic_subclass(annotation: type) -> bool:
142     return isinstance(annotation, type) and issubclass(
143         annotation, Generic  # type:ignore
144     )
145 
146 
147 def is_generic(annotation: type) -> bool:
148     """Returns True if the annotation is or extends a generic."""
149 
150     return (
151         # TODO: These two lines appear to have the same effect. When will an
152         #       annotation have parameters but not satisfy the first condition?
153         (is_generic_subclass(annotation) or is_concrete_generic(annotation))
154         and bool(get_parameters(annotation))
155     )
156 
157 
158 def is_type_var(annotation: Type) -> bool:
159     """Returns True if the annotation is a TypeVar."""
160 
161     return isinstance(annotation, TypeVar)
162 
163 
164 def get_parameters(annotation: Type) -> Union[Tuple[object], Tuple[()]]:
165     if (
166         isinstance(annotation, _GenericAlias)
167         or isinstance(annotation, type)
168         and issubclass(annotation, Generic)  # type:ignore
169         and annotation is not Generic
170     ):
171         return annotation.__parameters__
172     else:
173         return ()  # pragma: no cover
174 
175 
176 @overload
177 def _ast_replace_union_operation(expr: ast.expr) -> ast.expr:
178     ...
179 
180 
181 @overload
182 def _ast_replace_union_operation(expr: ast.Expr) -> ast.Expr:
183     ...
184 
185 
186 def _ast_replace_union_operation(
187     expr: Union[ast.Expr, ast.expr]
188 ) -> Union[ast.Expr, ast.expr]:
189     if isinstance(expr, ast.Expr) and isinstance(
190         expr.value, (ast.BinOp, ast.Subscript)
191     ):
192         expr = ast.Expr(_ast_replace_union_operation(expr.value))
193     elif isinstance(expr, ast.BinOp):
194         left = _ast_replace_union_operation(expr.left)
195         right = _ast_replace_union_operation(expr.right)
196         expr = ast.Subscript(
197             ast.Name(id="Union"),
198             ast.Tuple([left, right], ast.Load()),
199             ast.Load(),
200         )
201     elif isinstance(expr, ast.Tuple):
202         expr = ast.Tuple(
203             [_ast_replace_union_operation(elt) for elt in expr.elts],
204             ast.Load(),
205         )
206     elif isinstance(expr, ast.Subscript):
207         if hasattr(ast, "Index") and isinstance(expr.slice, ast.Index):
208             expr = ast.Subscript(
209                 expr.value,
210                 # The cast is required for mypy on python 3.7 and 3.8
211                 ast.Index(_ast_replace_union_operation(cast(Any, expr.slice).value)),
212                 ast.Load(),
213             )
214         elif isinstance(expr.slice, (ast.BinOp, ast.Tuple)):
215             expr = ast.Subscript(
216                 expr.value,
217                 _ast_replace_union_operation(expr.slice),
218                 ast.Load(),
219             )
220 
221     return expr
222 
223 
224 def eval_type(
225     type_: Any,
226     globalns: Optional[Dict] = None,
227     localns: Optional[Dict] = None,
228 ) -> Type:
229     """Evaluates a type, resolving forward references."""
230     from strawberry.auto import StrawberryAuto
231     from strawberry.lazy_type import StrawberryLazyReference
232     from strawberry.private import StrawberryPrivate
233 
234     globalns = globalns or {}
235     # If this is not a string, maybe its args are (e.g. List["Foo"])
236     if isinstance(type_, ForwardRef):
237         # For Python 3.10+, we can use the built-in _eval_type function directly.
238         # It will handle "|" notations properly
239         if sys.version_info < (3, 10):
240             parsed = _ast_replace_union_operation(
241                 cast(ast.Expr, ast.parse(type_.__forward_arg__).body[0])
242             )
243 
244             # We replaced "a | b" with "Union[a, b], so make sure Union can be resolved
245             # at globalns because it may not be there
246             if "Union" not in globalns:
247                 globalns["Union"] = Union
248 
249             assert ast_unparse
250             type_ = ForwardRef(ast_unparse(parsed))
251 
252         return _eval_type(type_, globalns, localns)
253 
254     origin = get_origin(type_)
255     if origin is not None:
256         args = get_args(type_)
257         if origin is Annotated:
258             for arg in args[1:]:
259                 if isinstance(arg, StrawberryPrivate):
260                     return type_
261 
262                 if isinstance(arg, StrawberryLazyReference):
263                     remaining_args = [
264                         a
265                         for a in args[1:]
266                         if not isinstance(arg, StrawberryLazyReference)
267                     ]
268                     args = (arg.resolve_forward_ref(args[0]), *remaining_args)
269                     break
270                 if isinstance(arg, StrawberryAuto):
271                     remaining_args = [
272                         a for a in args[1:] if not isinstance(arg, StrawberryAuto)
273                     ]
274                     args = (arg, *remaining_args)
275                     break
276 
277             # If we have only a StrawberryLazyReference and no more annotations,
278             # we need to return the argument directly because Annotated
279             # will raise an error if trying to instantiate it with only
280             # one argument.
281             if len(args) == 1:
282                 return args[0]
283 
284         # python 3.10 will return UnionType for origin, and it cannot be
285         # subscripted like Union[Foo, Bar]
286         if sys.version_info >= (3, 10):
287             from types import UnionType
288 
289             if origin is UnionType:
290                 origin = Union
291 
292         # Future annotations in older versions will eval generic aliases to their
293         # real types (i.e. List[foo] will have its origin set to list instead
294         # of List). If that type is not subscriptable, retrieve its generic
295         # alias version instead.
296         if sys.version_info < (3, 9) and not hasattr(origin, "__class_getitem__"):
297             origin = get_generic_alias(origin)
298 
299         type_ = (
300             origin[tuple(eval_type(a, globalns, localns) for a in args)]
301             if args
302             else origin
303         )
304 
305     return type_
306 
307 
308 _T = TypeVar("_T")
309 
310 
311 def __dataclass_transform__(
312     *,
313     eq_default: bool = True,
314     order_default: bool = False,
315     kw_only_default: bool = False,
316     field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()),
317 ) -> Callable[[_T], _T]:
318     return lambda a: a
319
```
--- 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/utils/typing.py b/strawberry/utils/typing.py
--- a/strawberry/utils/typing.py
+++ b/strawberry/utils/typing.py
@@ -1,4 +1,5 @@
 import ast
+import re
 import sys
 import typing
 from collections.abc import AsyncGenerator
@@ -221,6 +222,11 @@
     return expr
 
 
+_annotated_re = re.compile(
+    r"(Annotated\[)(?P<type>\w*),(?P<args>.*)(\])",
+)
+
+
 def eval_type(
     type_: Any,
     globalns: Optional[Dict] = None,
@@ -249,6 +255,37 @@
             assert ast_unparse
             type_ = ForwardRef(ast_unparse(parsed))
 
+        # When using forward refs, the whole
+        # Annotated[SomeType, strabwerry.lazy("type.module")] is a forward ref,
+        # and trying to _eval_type on it will fail. Take a different approach
+        # here to resolve lazy types by execing the annotated args and resolving
+        # the type directly.
+        annotated_match = _annotated_re.search(type_.__forward_arg__)
+        if annotated_match:
+            gdict = annotated_match.groupdict()
+            # FIXME: Eval the remaining annotated args to get their real values
+            # We might want to refactor how we import lazy modules to avoid having
+            # to eval the code in here
+            args = eval(f'({gdict["args"]}, )', globalns, localns)  # noqa: PGH001
+            lazy_ref = next(
+                (arg for arg in args if isinstance(arg, StrawberryLazyReference)),
+                None,
+            )
+            if lazy_ref is not None:
+                remaining = [
+                    a for a in args if not isinstance(a, StrawberryLazyReference)
+                ]
+                type_ = lazy_ref.resolve_forward_ref(ForwardRef(gdict["type"]))
+                # If we only had a StrawberryLazyReference, we can return the type
+                # directly. It already did its job!
+                if not remaining:
+                    return type_
+
+                # Otherwise return the type annotated with the remaining annotations
+                return Annotated.__class_getitem__(  # type: ignore
+                    (type_, *remaining),
+                )
+
         return _eval_type(type_, globalns, localns)
 
     origin = get_origin(type_)

{"golden_diff": "diff --git a/strawberry/utils/typing.py b/strawberry/utils/typing.py\n--- a/strawberry/utils/typing.py\n+++ b/strawberry/utils/typing.py\n@@ -1,4 +1,5 @@\n import ast\n+import re\n import sys\n import typing\n from collections.abc import AsyncGenerator\n@@ -221,6 +222,11 @@\n     return expr\n \n \n+_annotated_re = re.compile(\n+    r\"(Annotated\\[)(?P<type>\\w*),(?P<args>.*)(\\])\",\n+)\n+\n+\n def eval_type(\n     type_: Any,\n     globalns: Optional[Dict] = None,\n@@ -249,6 +255,37 @@\n             assert ast_unparse\n             type_ = ForwardRef(ast_unparse(parsed))\n \n+        # When using forward refs, the whole\n+        # Annotated[SomeType, strabwerry.lazy(\"type.module\")] is a forward ref,\n+        # and trying to _eval_type on it will fail. Take a different approach\n+        # here to resolve lazy types by execing the annotated args and resolving\n+        # the type directly.\n+        annotated_match = _annotated_re.search(type_.__forward_arg__)\n+        if annotated_match:\n+            gdict = annotated_match.groupdict()\n+            # FIXME: Eval the remaining annotated args to get their real values\n+            # We might want to refactor how we import lazy modules to avoid having\n+            # to eval the code in here\n+            args = eval(f'({gdict[\"args\"]}, )', globalns, localns)  # noqa: PGH001\n+            lazy_ref = next(\n+                (arg for arg in args if isinstance(arg, StrawberryLazyReference)),\n+                None,\n+            )\n+            if lazy_ref is not None:\n+                remaining = [\n+                    a for a in args if not isinstance(a, StrawberryLazyReference)\n+                ]\n+                type_ = lazy_ref.resolve_forward_ref(ForwardRef(gdict[\"type\"]))\n+                # If we only had a StrawberryLazyReference, we can return the type\n+                # directly. It already did its job!\n+                if not remaining:\n+                    return type_\n+\n+                # Otherwise return the type annotated with the remaining annotations\n+                return Annotated.__class_getitem__(  # type: ignore\n+                    (type_, *remaining),\n+                )\n+\n         return _eval_type(type_, globalns, localns)\n \n     origin = get_origin(type_)\n", "issue": "new strawberry.lazy not compatible with from __future__ import annotations\n# Description\r\n\r\nThe new way of lazy referencing via strawberry.lazy is not compatible with \r\n`from __future__ import annotations`\r\n\r\nIt would be nice to have compatibility as typing.Self is not available for python <=3.10 (the main reason to have `from __future__ import annotations`)\n", "before_files": [{"content": "import ast\nimport sys\nimport typing\nfrom collections.abc import AsyncGenerator\nfrom functools import lru_cache\nfrom typing import (  # type: ignore\n    TYPE_CHECKING,\n    Any,\n    Callable,\n    ClassVar,\n    Dict,\n    ForwardRef,\n    Generic,\n    Optional,\n    Tuple,\n    Type,\n    TypeVar,\n    Union,\n    _eval_type,\n    _GenericAlias,\n    _SpecialForm,\n    cast,\n    overload,\n)\nfrom typing_extensions import Annotated, get_args, get_origin\n\nast_unparse = getattr(ast, \"unparse\", None)\n# ast.unparse is only available on python 3.9+. For older versions we will\n# use `astunparse.unparse`.\n# We are also using \"not TYPE_CHECKING\" here because mypy gives an erorr\n# on tests because \"astunparse\" is missing stubs, but the mypy action says\n# that the comment is unused.\nif not TYPE_CHECKING and ast_unparse is None:\n    import astunparse\n\n    ast_unparse = astunparse.unparse\n\n\n@lru_cache()\ndef get_generic_alias(type_: Type) -> Type:\n    \"\"\"Get the generic alias for a type.\n\n    Given a type, its generic alias from `typing` module will be returned\n    if it exists. For example:\n\n        >>> get_generic_alias(list)\n        typing.List\n        >>> get_generic_alias(dict)\n        typing.Dict\n\n    This is mostly useful for python versions prior to 3.9, to get a version\n    of a concrete type which supports `__class_getitem__`. In 3.9+ types like\n    `list`/`dict`/etc are subscriptable and can be used directly instead\n    of their generic alias version.\n    \"\"\"\n    if isinstance(type_, _SpecialForm):\n        return type_\n\n    for attr_name in dir(typing):\n        # ignore private attributes, they are not Generic aliases\n        if attr_name.startswith(\"_\"):  # pragma: no cover\n            continue\n\n        attr = getattr(typing, attr_name)\n        # _GenericAlias overrides all the methods that we can use to know if\n        # this is a subclass of it. But if it has an \"_inst\" attribute\n        # then it for sure is a _GenericAlias\n        if hasattr(attr, \"_inst\") and attr.__origin__ is type_:\n            return attr\n\n    raise AssertionError(f\"No GenericAlias available for {type_}\")  # pragma: no cover\n\n\ndef is_list(annotation: object) -> bool:\n    \"\"\"Returns True if annotation is a List\"\"\"\n\n    annotation_origin = getattr(annotation, \"__origin__\", None)\n\n    return annotation_origin == list\n\n\ndef is_union(annotation: object) -> bool:\n    \"\"\"Returns True if annotation is a Union\"\"\"\n\n    # this check is needed because unions declared with the new syntax `A | B`\n    # don't have a `__origin__` property on them, but they are instances of\n    # `UnionType`, which is only available in Python 3.10+\n    if sys.version_info >= (3, 10):\n        from types import UnionType\n\n        if isinstance(annotation, UnionType):\n            return True\n\n    # unions declared as Union[A, B] fall through to this check, even on python 3.10+\n\n    annotation_origin = getattr(annotation, \"__origin__\", None)\n\n    return annotation_origin == Union\n\n\ndef is_optional(annotation: Type) -> bool:\n    \"\"\"Returns True if the annotation is Optional[SomeType]\"\"\"\n\n    # Optionals are represented as unions\n\n    if not is_union(annotation):\n        return False\n\n    types = annotation.__args__\n\n    # A Union to be optional needs to have at least one None type\n    return any(x == None.__class__ for x in types)\n\n\ndef get_optional_annotation(annotation: Type) -> Type:\n    types = annotation.__args__\n\n    non_none_types = tuple(x for x in types if x != None.__class__)\n\n    # if we have multiple non none types we want to return a copy of this\n    # type (normally a Union type).\n\n    if len(non_none_types) > 1:\n        return annotation.copy_with(non_none_types)\n\n    return non_none_types[0]\n\n\ndef get_list_annotation(annotation: Type) -> Type:\n    return annotation.__args__[0]\n\n\ndef is_concrete_generic(annotation: type) -> bool:\n    ignored_generics = (list, tuple, Union, ClassVar, AsyncGenerator)\n    return (\n        isinstance(annotation, _GenericAlias)\n        and annotation.__origin__ not in ignored_generics\n    )\n\n\ndef is_generic_subclass(annotation: type) -> bool:\n    return isinstance(annotation, type) and issubclass(\n        annotation, Generic  # type:ignore\n    )\n\n\ndef is_generic(annotation: type) -> bool:\n    \"\"\"Returns True if the annotation is or extends a generic.\"\"\"\n\n    return (\n        # TODO: These two lines appear to have the same effect. When will an\n        #       annotation have parameters but not satisfy the first condition?\n        (is_generic_subclass(annotation) or is_concrete_generic(annotation))\n        and bool(get_parameters(annotation))\n    )\n\n\ndef is_type_var(annotation: Type) -> bool:\n    \"\"\"Returns True if the annotation is a TypeVar.\"\"\"\n\n    return isinstance(annotation, TypeVar)\n\n\ndef get_parameters(annotation: Type) -> Union[Tuple[object], Tuple[()]]:\n    if (\n        isinstance(annotation, _GenericAlias)\n        or isinstance(annotation, type)\n        and issubclass(annotation, Generic)  # type:ignore\n        and annotation is not Generic\n    ):\n        return annotation.__parameters__\n    else:\n        return ()  # pragma: no cover\n\n\n@overload\ndef _ast_replace_union_operation(expr: ast.expr) -> ast.expr:\n    ...\n\n\n@overload\ndef _ast_replace_union_operation(expr: ast.Expr) -> ast.Expr:\n    ...\n\n\ndef _ast_replace_union_operation(\n    expr: Union[ast.Expr, ast.expr]\n) -> Union[ast.Expr, ast.expr]:\n    if isinstance(expr, ast.Expr) and isinstance(\n        expr.value, (ast.BinOp, ast.Subscript)\n    ):\n        expr = ast.Expr(_ast_replace_union_operation(expr.value))\n    elif isinstance(expr, ast.BinOp):\n        left = _ast_replace_union_operation(expr.left)\n        right = _ast_replace_union_operation(expr.right)\n        expr = ast.Subscript(\n            ast.Name(id=\"Union\"),\n            ast.Tuple([left, right], ast.Load()),\n            ast.Load(),\n        )\n    elif isinstance(expr, ast.Tuple):\n        expr = ast.Tuple(\n            [_ast_replace_union_operation(elt) for elt in expr.elts],\n            ast.Load(),\n        )\n    elif isinstance(expr, ast.Subscript):\n        if hasattr(ast, \"Index\") and isinstance(expr.slice, ast.Index):\n            expr = ast.Subscript(\n                expr.value,\n                # The cast is required for mypy on python 3.7 and 3.8\n                ast.Index(_ast_replace_union_operation(cast(Any, expr.slice).value)),\n                ast.Load(),\n            )\n        elif isinstance(expr.slice, (ast.BinOp, ast.Tuple)):\n            expr = ast.Subscript(\n                expr.value,\n                _ast_replace_union_operation(expr.slice),\n                ast.Load(),\n            )\n\n    return expr\n\n\ndef eval_type(\n    type_: Any,\n    globalns: Optional[Dict] = None,\n    localns: Optional[Dict] = None,\n) -> Type:\n    \"\"\"Evaluates a type, resolving forward references.\"\"\"\n    from strawberry.auto import StrawberryAuto\n    from strawberry.lazy_type import StrawberryLazyReference\n    from strawberry.private import StrawberryPrivate\n\n    globalns = globalns or {}\n    # If this is not a string, maybe its args are (e.g. List[\"Foo\"])\n    if isinstance(type_, ForwardRef):\n        # For Python 3.10+, we can use the built-in _eval_type function directly.\n        # It will handle \"|\" notations properly\n        if sys.version_info < (3, 10):\n            parsed = _ast_replace_union_operation(\n                cast(ast.Expr, ast.parse(type_.__forward_arg__).body[0])\n            )\n\n            # We replaced \"a | b\" with \"Union[a, b], so make sure Union can be resolved\n            # at globalns because it may not be there\n            if \"Union\" not in globalns:\n                globalns[\"Union\"] = Union\n\n            assert ast_unparse\n            type_ = ForwardRef(ast_unparse(parsed))\n\n        return _eval_type(type_, globalns, localns)\n\n    origin = get_origin(type_)\n    if origin is not None:\n        args = get_args(type_)\n        if origin is Annotated:\n            for arg in args[1:]:\n                if isinstance(arg, StrawberryPrivate):\n                    return type_\n\n                if isinstance(arg, StrawberryLazyReference):\n                    remaining_args = [\n                        a\n                        for a in args[1:]\n                        if not isinstance(arg, StrawberryLazyReference)\n                    ]\n                    args = (arg.resolve_forward_ref(args[0]), *remaining_args)\n                    break\n                if isinstance(arg, StrawberryAuto):\n                    remaining_args = [\n                        a for a in args[1:] if not isinstance(arg, StrawberryAuto)\n                    ]\n                    args = (arg, *remaining_args)\n                    break\n\n            # If we have only a StrawberryLazyReference and no more annotations,\n            # we need to return the argument directly because Annotated\n            # will raise an error if trying to instantiate it with only\n            # one argument.\n            if len(args) == 1:\n                return args[0]\n\n        # python 3.10 will return UnionType for origin, and it cannot be\n        # subscripted like Union[Foo, Bar]\n        if sys.version_info >= (3, 10):\n            from types import UnionType\n\n            if origin is UnionType:\n                origin = Union\n\n        # Future annotations in older versions will eval generic aliases to their\n        # real types (i.e. List[foo] will have its origin set to list instead\n        # of List). If that type is not subscriptable, retrieve its generic\n        # alias version instead.\n        if sys.version_info < (3, 9) and not hasattr(origin, \"__class_getitem__\"):\n            origin = get_generic_alias(origin)\n\n        type_ = (\n            origin[tuple(eval_type(a, globalns, localns) for a in args)]\n            if args\n            else origin\n        )\n\n    return type_\n\n\n_T = TypeVar(\"_T\")\n\n\ndef __dataclass_transform__(\n    *,\n    eq_default: bool = True,\n    order_default: bool = False,\n    kw_only_default: bool = False,\n    field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()),\n) -> Callable[[_T], _T]:\n    return lambda a: a\n", "path": "strawberry/utils/typing.py"}], "after_files": [{"content": "import ast\nimport re\nimport sys\nimport typing\nfrom collections.abc import AsyncGenerator\nfrom functools import lru_cache\nfrom typing import (  # type: ignore\n    TYPE_CHECKING,\n    Any,\n    Callable,\n    ClassVar,\n    Dict,\n    ForwardRef,\n    Generic,\n    Optional,\n    Tuple,\n    Type,\n    TypeVar,\n    Union,\n    _eval_type,\n    _GenericAlias,\n    _SpecialForm,\n    cast,\n    overload,\n)\nfrom typing_extensions import Annotated, get_args, get_origin\n\nast_unparse = getattr(ast, \"unparse\", None)\n# ast.unparse is only available on python 3.9+. For older versions we will\n# use `astunparse.unparse`.\n# We are also using \"not TYPE_CHECKING\" here because mypy gives an erorr\n# on tests because \"astunparse\" is missing stubs, but the mypy action says\n# that the comment is unused.\nif not TYPE_CHECKING and ast_unparse is None:\n    import astunparse\n\n    ast_unparse = astunparse.unparse\n\n\n@lru_cache()\ndef get_generic_alias(type_: Type) -> Type:\n    \"\"\"Get the generic alias for a type.\n\n    Given a type, its generic alias from `typing` module will be returned\n    if it exists. For example:\n\n        >>> get_generic_alias(list)\n        typing.List\n        >>> get_generic_alias(dict)\n        typing.Dict\n\n    This is mostly useful for python versions prior to 3.9, to get a version\n    of a concrete type which supports `__class_getitem__`. In 3.9+ types like\n    `list`/`dict`/etc are subscriptable and can be used directly instead\n    of their generic alias version.\n    \"\"\"\n    if isinstance(type_, _SpecialForm):\n        return type_\n\n    for attr_name in dir(typing):\n        # ignore private attributes, they are not Generic aliases\n        if attr_name.startswith(\"_\"):  # pragma: no cover\n            continue\n\n        attr = getattr(typing, attr_name)\n        # _GenericAlias overrides all the methods that we can use to know if\n        # this is a subclass of it. But if it has an \"_inst\" attribute\n        # then it for sure is a _GenericAlias\n        if hasattr(attr, \"_inst\") and attr.__origin__ is type_:\n            return attr\n\n    raise AssertionError(f\"No GenericAlias available for {type_}\")  # pragma: no cover\n\n\ndef is_list(annotation: object) -> bool:\n    \"\"\"Returns True if annotation is a List\"\"\"\n\n    annotation_origin = getattr(annotation, \"__origin__\", None)\n\n    return annotation_origin == list\n\n\ndef is_union(annotation: object) -> bool:\n    \"\"\"Returns True if annotation is a Union\"\"\"\n\n    # this check is needed because unions declared with the new syntax `A | B`\n    # don't have a `__origin__` property on them, but they are instances of\n    # `UnionType`, which is only available in Python 3.10+\n    if sys.version_info >= (3, 10):\n        from types import UnionType\n\n        if isinstance(annotation, UnionType):\n            return True\n\n    # unions declared as Union[A, B] fall through to this check, even on python 3.10+\n\n    annotation_origin = getattr(annotation, \"__origin__\", None)\n\n    return annotation_origin == Union\n\n\ndef is_optional(annotation: Type) -> bool:\n    \"\"\"Returns True if the annotation is Optional[SomeType]\"\"\"\n\n    # Optionals are represented as unions\n\n    if not is_union(annotation):\n        return False\n\n    types = annotation.__args__\n\n    # A Union to be optional needs to have at least one None type\n    return any(x == None.__class__ for x in types)\n\n\ndef get_optional_annotation(annotation: Type) -> Type:\n    types = annotation.__args__\n\n    non_none_types = tuple(x for x in types if x != None.__class__)\n\n    # if we have multiple non none types we want to return a copy of this\n    # type (normally a Union type).\n\n    if len(non_none_types) > 1:\n        return annotation.copy_with(non_none_types)\n\n    return non_none_types[0]\n\n\ndef get_list_annotation(annotation: Type) -> Type:\n    return annotation.__args__[0]\n\n\ndef is_concrete_generic(annotation: type) -> bool:\n    ignored_generics = (list, tuple, Union, ClassVar, AsyncGenerator)\n    return (\n        isinstance(annotation, _GenericAlias)\n        and annotation.__origin__ not in ignored_generics\n    )\n\n\ndef is_generic_subclass(annotation: type) -> bool:\n    return isinstance(annotation, type) and issubclass(\n        annotation, Generic  # type:ignore\n    )\n\n\ndef is_generic(annotation: type) -> bool:\n    \"\"\"Returns True if the annotation is or extends a generic.\"\"\"\n\n    return (\n        # TODO: These two lines appear to have the same effect. When will an\n        #       annotation have parameters but not satisfy the first condition?\n        (is_generic_subclass(annotation) or is_concrete_generic(annotation))\n        and bool(get_parameters(annotation))\n    )\n\n\ndef is_type_var(annotation: Type) -> bool:\n    \"\"\"Returns True if the annotation is a TypeVar.\"\"\"\n\n    return isinstance(annotation, TypeVar)\n\n\ndef get_parameters(annotation: Type) -> Union[Tuple[object], Tuple[()]]:\n    if (\n        isinstance(annotation, _GenericAlias)\n        or isinstance(annotation, type)\n        and issubclass(annotation, Generic)  # type:ignore\n        and annotation is not Generic\n    ):\n        return annotation.__parameters__\n    else:\n        return ()  # pragma: no cover\n\n\n@overload\ndef _ast_replace_union_operation(expr: ast.expr) -> ast.expr:\n    ...\n\n\n@overload\ndef _ast_replace_union_operation(expr: ast.Expr) -> ast.Expr:\n    ...\n\n\ndef _ast_replace_union_operation(\n    expr: Union[ast.Expr, ast.expr]\n) -> Union[ast.Expr, ast.expr]:\n    if isinstance(expr, ast.Expr) and isinstance(\n        expr.value, (ast.BinOp, ast.Subscript)\n    ):\n        expr = ast.Expr(_ast_replace_union_operation(expr.value))\n    elif isinstance(expr, ast.BinOp):\n        left = _ast_replace_union_operation(expr.left)\n        right = _ast_replace_union_operation(expr.right)\n        expr = ast.Subscript(\n            ast.Name(id=\"Union\"),\n            ast.Tuple([left, right], ast.Load()),\n            ast.Load(),\n        )\n    elif isinstance(expr, ast.Tuple):\n        expr = ast.Tuple(\n            [_ast_replace_union_operation(elt) for elt in expr.elts],\n            ast.Load(),\n        )\n    elif isinstance(expr, ast.Subscript):\n        if hasattr(ast, \"Index\") and isinstance(expr.slice, ast.Index):\n            expr = ast.Subscript(\n                expr.value,\n                # The cast is required for mypy on python 3.7 and 3.8\n                ast.Index(_ast_replace_union_operation(cast(Any, expr.slice).value)),\n                ast.Load(),\n            )\n        elif isinstance(expr.slice, (ast.BinOp, ast.Tuple)):\n            expr = ast.Subscript(\n                expr.value,\n                _ast_replace_union_operation(expr.slice),\n                ast.Load(),\n            )\n\n    return expr\n\n\n_annotated_re = re.compile(\n    r\"(Annotated\\[)(?P<type>\\w*),(?P<args>.*)(\\])\",\n)\n\n\ndef eval_type(\n    type_: Any,\n    globalns: Optional[Dict] = None,\n    localns: Optional[Dict] = None,\n) -> Type:\n    \"\"\"Evaluates a type, resolving forward references.\"\"\"\n    from strawberry.auto import StrawberryAuto\n    from strawberry.lazy_type import StrawberryLazyReference\n    from strawberry.private import StrawberryPrivate\n\n    globalns = globalns or {}\n    # If this is not a string, maybe its args are (e.g. List[\"Foo\"])\n    if isinstance(type_, ForwardRef):\n        # For Python 3.10+, we can use the built-in _eval_type function directly.\n        # It will handle \"|\" notations properly\n        if sys.version_info < (3, 10):\n            parsed = _ast_replace_union_operation(\n                cast(ast.Expr, ast.parse(type_.__forward_arg__).body[0])\n            )\n\n            # We replaced \"a | b\" with \"Union[a, b], so make sure Union can be resolved\n            # at globalns because it may not be there\n            if \"Union\" not in globalns:\n                globalns[\"Union\"] = Union\n\n            assert ast_unparse\n            type_ = ForwardRef(ast_unparse(parsed))\n\n        # When using forward refs, the whole\n        # Annotated[SomeType, strabwerry.lazy(\"type.module\")] is a forward ref,\n        # and trying to _eval_type on it will fail. Take a different approach\n        # here to resolve lazy types by execing the annotated args and resolving\n        # the type directly.\n        annotated_match = _annotated_re.search(type_.__forward_arg__)\n        if annotated_match:\n            gdict = annotated_match.groupdict()\n            # FIXME: Eval the remaining annotated args to get their real values\n            # We might want to refactor how we import lazy modules to avoid having\n            # to eval the code in here\n            args = eval(f'({gdict[\"args\"]}, )', globalns, localns)  # noqa: PGH001\n            lazy_ref = next(\n                (arg for arg in args if isinstance(arg, StrawberryLazyReference)),\n                None,\n            )\n            if lazy_ref is not None:\n                remaining = [\n                    a for a in args if not isinstance(a, StrawberryLazyReference)\n                ]\n                type_ = lazy_ref.resolve_forward_ref(ForwardRef(gdict[\"type\"]))\n                # If we only had a StrawberryLazyReference, we can return the type\n                # directly. It already did its job!\n                if not remaining:\n                    return type_\n\n                # Otherwise return the type annotated with the remaining annotations\n                return Annotated.__class_getitem__(  # type: ignore\n                    (type_, *remaining),\n                )\n\n        return _eval_type(type_, globalns, localns)\n\n    origin = get_origin(type_)\n    if origin is not None:\n        args = get_args(type_)\n        if origin is Annotated:\n            for arg in args[1:]:\n                if isinstance(arg, StrawberryPrivate):\n                    return type_\n\n                if isinstance(arg, StrawberryLazyReference):\n                    remaining_args = [\n                        a\n                        for a in args[1:]\n                        if not isinstance(arg, StrawberryLazyReference)\n                    ]\n                    args = (arg.resolve_forward_ref(args[0]), *remaining_args)\n                    break\n                if isinstance(arg, StrawberryAuto):\n                    remaining_args = [\n                        a for a in args[1:] if not isinstance(arg, StrawberryAuto)\n                    ]\n                    args = (arg, *remaining_args)\n                    break\n\n            # If we have only a StrawberryLazyReference and no more annotations,\n            # we need to return the argument directly because Annotated\n            # will raise an error if trying to instantiate it with only\n            # one argument.\n            if len(args) == 1:\n                return args[0]\n\n        # python 3.10 will return UnionType for origin, and it cannot be\n        # subscripted like Union[Foo, Bar]\n        if sys.version_info >= (3, 10):\n            from types import UnionType\n\n            if origin is UnionType:\n                origin = Union\n\n        # Future annotations in older versions will eval generic aliases to their\n        # real types (i.e. List[foo] will have its origin set to list instead\n        # of List). If that type is not subscriptable, retrieve its generic\n        # alias version instead.\n        if sys.version_info < (3, 9) and not hasattr(origin, \"__class_getitem__\"):\n            origin = get_generic_alias(origin)\n\n        type_ = (\n            origin[tuple(eval_type(a, globalns, localns) for a in args)]\n            if args\n            else origin\n        )\n\n    return type_\n\n\n_T = TypeVar(\"_T\")\n\n\ndef __dataclass_transform__(\n    *,\n    eq_default: bool = True,\n    order_default: bool = False,\n    kw_only_default: bool = False,\n    field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()),\n) -> Callable[[_T], _T]:\n    return lambda a: a\n", "path": "strawberry/utils/typing.py"}]}