We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Only pass info when resolver asks for it
I was thinking of making the API slightly easier for resolvers

so instead of having:

```python
@strawberry.type
class Query:
    @strawberry.field
    def user(self, info) -> User:
        return User(name="Patrick", age=100)
```

we could have this:

```python
@strawberry.type
class Query:
    @strawberry.field
    def user(self) -> User:
        return User(name="Patrick", age=100)
```

the difference is minimal, but it should make the library slightly more user-friendly 😊

--- 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/field.py`
Content:
```
1 import dataclasses
2 import enum
3 import inspect
4 import typing
5 
6 from graphql import GraphQLField, GraphQLInputField
7 
8 from .constants import IS_STRAWBERRY_FIELD
9 from .exceptions import MissingArgumentsAnnotationsError, MissingReturnAnnotationError
10 from .type_converter import REGISTRY, get_graphql_type_for_annotation
11 from .utils.arguments import convert_args
12 from .utils.inspect import get_func_args
13 from .utils.lazy_property import lazy_property
14 from .utils.str_converters import to_camel_case
15 
16 
17 class LazyFieldWrapper:
18     """A lazy wrapper for a strawberry field.
19     This allows to use cyclic dependencies in a strawberry fields:
20 
21     >>> @strawberry.type
22     >>> class TypeA:
23     >>>     @strawberry.field
24     >>>     def type_b(self, info) -> "TypeB":
25     >>>         from .type_b import TypeB
26     >>>         return TypeB()
27     """
28 
29     def __init__(
30         self,
31         obj,
32         *,
33         is_input=False,
34         is_subscription=False,
35         resolver=None,
36         name=None,
37         description=None,
38         permission_classes=None
39     ):
40         self._wrapped_obj = obj
41         self.is_subscription = is_subscription
42         self.is_input = is_input
43         self.field_name = name
44         self.field_resolver = resolver
45         self.field_description = description
46         self.permission_classes = permission_classes or []
47 
48         if callable(self._wrapped_obj):
49             self._check_has_annotations(self._wrapped_obj)
50 
51     def _check_has_annotations(self, func):
52         # using annotations without passing from typing.get_type_hints
53         # as we don't need the actually types for the annotations
54         annotations = func.__annotations__
55         name = func.__name__
56 
57         if "return" not in annotations:
58             raise MissingReturnAnnotationError(name)
59 
60         function_arguments = set(get_func_args(func)) - {"root", "self", "info"}
61 
62         arguments_annotations = {
63             key: value
64             for key, value in annotations.items()
65             if key not in ["root", "info", "return"]
66         }
67 
68         annotated_function_arguments = set(arguments_annotations.keys())
69         arguments_missing_annotations = (
70             function_arguments - annotated_function_arguments
71         )
72 
73         if len(arguments_missing_annotations) > 0:
74             raise MissingArgumentsAnnotationsError(name, arguments_missing_annotations)
75 
76     def __getattr__(self, attr):
77         if attr in self.__dict__:
78             return getattr(self, attr)
79 
80         return getattr(self._wrapped_obj, attr)
81 
82     def __call__(self, *args, **kwargs):
83         return self._wrapped_obj(self, *args, **kwargs)
84 
85     def _get_permissions(self):
86         """
87         Gets all permissions defined in the permission classes
88         >>> strawberry.field(permission_classes=[IsAuthenticated])
89         """
90         return (permission() for permission in self.permission_classes)
91 
92     def _check_permissions(self, source, info, **kwargs):
93         """
94         Checks if the permission should be accepted and
95         raises an exception if not
96         """
97         for permission in self._get_permissions():
98             if not permission.has_permission(source, info, **kwargs):
99                 message = getattr(permission, "message", None)
100                 raise PermissionError(message)
101 
102     @lazy_property
103     def field(self):
104         return _get_field(
105             self._wrapped_obj,
106             is_input=self.is_input,
107             is_subscription=self.is_subscription,
108             name=self.field_name,
109             description=self.field_description,
110             check_permission=self._check_permissions,
111         )
112 
113 
114 class strawberry_field(dataclasses.Field):
115     """A small wrapper for a field in strawberry.
116 
117     You shouldn't be using this directly as this is used internally
118     when using `strawberry.field`.
119 
120     This allows to use the following two syntaxes when using the type
121     decorator:
122 
123     >>> class X:
124     >>>     field_abc: str = strawberry.field(description="ABC")
125 
126     >>> class X:
127     >>>     @strawberry.field(description="ABC")
128     >>>     def field_a(self, info) -> str:
129     >>>         return "abc"
130 
131     When calling this class as strawberry_field it creates a field
132     that stores metadata (such as field description). In addition
133     to that it also acts as decorator when called as a function,
134     allowing us to us both syntaxes.
135     """
136 
137     def __init__(
138         self,
139         *,
140         is_input=False,
141         is_subscription=False,
142         resolver=None,
143         name=None,
144         description=None,
145         metadata=None,
146         permission_classes=None
147     ):
148         self.field_name = name
149         self.field_description = description
150         self.field_resolver = resolver
151         self.is_subscription = is_subscription
152         self.is_input = is_input
153         self.field_permission_classes = permission_classes
154 
155         super().__init__(
156             # TODO:
157             default=dataclasses.MISSING,
158             default_factory=dataclasses.MISSING,
159             init=resolver is None,
160             repr=True,
161             hash=None,
162             # TODO: this needs to be False when init is False
163             # we could turn it to True when and if we have a default
164             # probably can't be True when passing a resolver
165             compare=is_input,
166             metadata=metadata,
167         )
168 
169     def __call__(self, wrap):
170         setattr(wrap, IS_STRAWBERRY_FIELD, True)
171 
172         self.field_description = self.field_description or wrap.__doc__
173 
174         return LazyFieldWrapper(
175             wrap,
176             is_input=self.is_input,
177             is_subscription=self.is_subscription,
178             resolver=self.field_resolver,
179             name=self.field_name,
180             description=self.field_description,
181             permission_classes=self.field_permission_classes,
182         )
183 
184 
185 def _get_field(
186     wrap,
187     *,
188     is_input=False,
189     is_subscription=False,
190     name=None,
191     description=None,
192     check_permission=None
193 ):
194     name = wrap.__name__
195 
196     annotations = typing.get_type_hints(wrap, None, REGISTRY)
197     parameters = inspect.signature(wrap).parameters
198     field_type = get_graphql_type_for_annotation(annotations["return"], name)
199 
200     arguments_annotations = {
201         key: value
202         for key, value in annotations.items()
203         if key not in ["info", "return"]
204     }
205 
206     arguments = {
207         to_camel_case(name): get_graphql_type_for_annotation(
208             annotation, name, parameters[name].default != inspect._empty
209         )
210         for name, annotation in arguments_annotations.items()
211     }
212 
213     def resolver(source, info, **kwargs):
214         if check_permission:
215             check_permission(source, info, **kwargs)
216 
217         kwargs = convert_args(kwargs, arguments_annotations)
218         result = wrap(source, info, **kwargs)
219 
220         # graphql-core expects a resolver for an Enum type to return
221         # the enum's *value* (not its name or an instance of the enum).
222         if isinstance(result, enum.Enum):
223             return result.value
224 
225         return result
226 
227     field_params = {}
228 
229     if not is_input:
230         field_params["args"] = arguments
231 
232         if is_subscription:
233 
234             def _resolve(event, info):
235                 if check_permission:
236                     check_permission(event, info)
237 
238                 return event
239 
240             field_params.update({"subscribe": resolver, "resolve": _resolve})
241         else:
242             field_params.update({"resolve": resolver})
243 
244     field_params["description"] = description or wrap.__doc__
245 
246     FieldType = GraphQLInputField if is_input else GraphQLField
247 
248     return FieldType(field_type, **field_params)
249 
250 
251 def field(
252     wrap=None,
253     *,
254     name=None,
255     description=None,
256     resolver=None,
257     is_input=False,
258     is_subscription=False,
259     permission_classes=None
260 ):
261     """Annotates a method or property as a GraphQL field.
262 
263     This is normally used inside a type declaration:
264 
265     >>> @strawberry.type:
266     >>> class X:
267     >>>     field_abc: str = strawberry.field(description="ABC")
268 
269     >>>     @strawberry.field(description="ABC")
270     >>>     def field_with_resolver(self, info) -> str:
271     >>>         return "abc"
272 
273     it can be used both as decorator and as a normal function.
274     """
275 
276     field = strawberry_field(
277         name=name,
278         description=description,
279         resolver=resolver,
280         is_input=is_input,
281         is_subscription=is_subscription,
282         permission_classes=permission_classes,
283     )
284 
285     # when calling this with parens we are going to return a strawberry_field
286     # instance, so it can be used as both decorator and function.
287 
288     if wrap is None:
289         return field
290 
291     # otherwise we run the decorator directly,
292     # when called as @strawberry.field, without parens.
293 
294     return field(wrap)
295
```
--- 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/field.py b/strawberry/field.py
--- a/strawberry/field.py
+++ b/strawberry/field.py
@@ -214,8 +214,27 @@
         if check_permission:
             check_permission(source, info, **kwargs)
 
+        # the following code allows to omit info and root arguments
+        # by inspecting the original resolver arguments,
+        # if it asks for self, the source will be passed as first argument
+        # if it asks for root, the source it will be passed as kwarg
+        # if it asks for info, the info will be passed as kwarg
+
         kwargs = convert_args(kwargs, arguments_annotations)
-        result = wrap(source, info, **kwargs)
+        function_args = get_func_args(wrap)
+
+        args = []
+
+        if "self" in function_args:
+            args.append(wrap)
+
+        if "root" in function_args:
+            kwargs["root"] = source
+
+        if "info" in function_args:
+            kwargs["info"] = info
+
+        result = wrap(*args, **kwargs)
 
         # graphql-core expects a resolver for an Enum type to return
         # the enum's *value* (not its name or an instance of the enum).

{"golden_diff": "diff --git a/strawberry/field.py b/strawberry/field.py\n--- a/strawberry/field.py\n+++ b/strawberry/field.py\n@@ -214,8 +214,27 @@\n         if check_permission:\n             check_permission(source, info, **kwargs)\n \n+        # the following code allows to omit info and root arguments\n+        # by inspecting the original resolver arguments,\n+        # if it asks for self, the source will be passed as first argument\n+        # if it asks for root, the source it will be passed as kwarg\n+        # if it asks for info, the info will be passed as kwarg\n+\n         kwargs = convert_args(kwargs, arguments_annotations)\n-        result = wrap(source, info, **kwargs)\n+        function_args = get_func_args(wrap)\n+\n+        args = []\n+\n+        if \"self\" in function_args:\n+            args.append(wrap)\n+\n+        if \"root\" in function_args:\n+            kwargs[\"root\"] = source\n+\n+        if \"info\" in function_args:\n+            kwargs[\"info\"] = info\n+\n+        result = wrap(*args, **kwargs)\n \n         # graphql-core expects a resolver for an Enum type to return\n         # the enum's *value* (not its name or an instance of the enum).\n", "issue": "Only pass info when resolver asks for it\nI was thinking of making the API slightly easier for resolvers\r\n\r\nso instead of having:\r\n\r\n```python\r\n@strawberry.type\r\nclass Query:\r\n    @strawberry.field\r\n    def user(self, info) -> User:\r\n        return User(name=\"Patrick\", age=100)\r\n```\r\n\r\nwe could have this:\r\n\r\n```python\r\n@strawberry.type\r\nclass Query:\r\n    @strawberry.field\r\n    def user(self) -> User:\r\n        return User(name=\"Patrick\", age=100)\r\n```\r\n\r\nthe difference is minimal, but it should make the library slightly more user-friendly \ud83d\ude0a\n", "before_files": [{"content": "import dataclasses\nimport enum\nimport inspect\nimport typing\n\nfrom graphql import GraphQLField, GraphQLInputField\n\nfrom .constants import IS_STRAWBERRY_FIELD\nfrom .exceptions import MissingArgumentsAnnotationsError, MissingReturnAnnotationError\nfrom .type_converter import REGISTRY, get_graphql_type_for_annotation\nfrom .utils.arguments import convert_args\nfrom .utils.inspect import get_func_args\nfrom .utils.lazy_property import lazy_property\nfrom .utils.str_converters import to_camel_case\n\n\nclass LazyFieldWrapper:\n    \"\"\"A lazy wrapper for a strawberry field.\n    This allows to use cyclic dependencies in a strawberry fields:\n\n    >>> @strawberry.type\n    >>> class TypeA:\n    >>>     @strawberry.field\n    >>>     def type_b(self, info) -> \"TypeB\":\n    >>>         from .type_b import TypeB\n    >>>         return TypeB()\n    \"\"\"\n\n    def __init__(\n        self,\n        obj,\n        *,\n        is_input=False,\n        is_subscription=False,\n        resolver=None,\n        name=None,\n        description=None,\n        permission_classes=None\n    ):\n        self._wrapped_obj = obj\n        self.is_subscription = is_subscription\n        self.is_input = is_input\n        self.field_name = name\n        self.field_resolver = resolver\n        self.field_description = description\n        self.permission_classes = permission_classes or []\n\n        if callable(self._wrapped_obj):\n            self._check_has_annotations(self._wrapped_obj)\n\n    def _check_has_annotations(self, func):\n        # using annotations without passing from typing.get_type_hints\n        # as we don't need the actually types for the annotations\n        annotations = func.__annotations__\n        name = func.__name__\n\n        if \"return\" not in annotations:\n            raise MissingReturnAnnotationError(name)\n\n        function_arguments = set(get_func_args(func)) - {\"root\", \"self\", \"info\"}\n\n        arguments_annotations = {\n            key: value\n            for key, value in annotations.items()\n            if key not in [\"root\", \"info\", \"return\"]\n        }\n\n        annotated_function_arguments = set(arguments_annotations.keys())\n        arguments_missing_annotations = (\n            function_arguments - annotated_function_arguments\n        )\n\n        if len(arguments_missing_annotations) > 0:\n            raise MissingArgumentsAnnotationsError(name, arguments_missing_annotations)\n\n    def __getattr__(self, attr):\n        if attr in self.__dict__:\n            return getattr(self, attr)\n\n        return getattr(self._wrapped_obj, attr)\n\n    def __call__(self, *args, **kwargs):\n        return self._wrapped_obj(self, *args, **kwargs)\n\n    def _get_permissions(self):\n        \"\"\"\n        Gets all permissions defined in the permission classes\n        >>> strawberry.field(permission_classes=[IsAuthenticated])\n        \"\"\"\n        return (permission() for permission in self.permission_classes)\n\n    def _check_permissions(self, source, info, **kwargs):\n        \"\"\"\n        Checks if the permission should be accepted and\n        raises an exception if not\n        \"\"\"\n        for permission in self._get_permissions():\n            if not permission.has_permission(source, info, **kwargs):\n                message = getattr(permission, \"message\", None)\n                raise PermissionError(message)\n\n    @lazy_property\n    def field(self):\n        return _get_field(\n            self._wrapped_obj,\n            is_input=self.is_input,\n            is_subscription=self.is_subscription,\n            name=self.field_name,\n            description=self.field_description,\n            check_permission=self._check_permissions,\n        )\n\n\nclass strawberry_field(dataclasses.Field):\n    \"\"\"A small wrapper for a field in strawberry.\n\n    You shouldn't be using this directly as this is used internally\n    when using `strawberry.field`.\n\n    This allows to use the following two syntaxes when using the type\n    decorator:\n\n    >>> class X:\n    >>>     field_abc: str = strawberry.field(description=\"ABC\")\n\n    >>> class X:\n    >>>     @strawberry.field(description=\"ABC\")\n    >>>     def field_a(self, info) -> str:\n    >>>         return \"abc\"\n\n    When calling this class as strawberry_field it creates a field\n    that stores metadata (such as field description). In addition\n    to that it also acts as decorator when called as a function,\n    allowing us to us both syntaxes.\n    \"\"\"\n\n    def __init__(\n        self,\n        *,\n        is_input=False,\n        is_subscription=False,\n        resolver=None,\n        name=None,\n        description=None,\n        metadata=None,\n        permission_classes=None\n    ):\n        self.field_name = name\n        self.field_description = description\n        self.field_resolver = resolver\n        self.is_subscription = is_subscription\n        self.is_input = is_input\n        self.field_permission_classes = permission_classes\n\n        super().__init__(\n            # TODO:\n            default=dataclasses.MISSING,\n            default_factory=dataclasses.MISSING,\n            init=resolver is None,\n            repr=True,\n            hash=None,\n            # TODO: this needs to be False when init is False\n            # we could turn it to True when and if we have a default\n            # probably can't be True when passing a resolver\n            compare=is_input,\n            metadata=metadata,\n        )\n\n    def __call__(self, wrap):\n        setattr(wrap, IS_STRAWBERRY_FIELD, True)\n\n        self.field_description = self.field_description or wrap.__doc__\n\n        return LazyFieldWrapper(\n            wrap,\n            is_input=self.is_input,\n            is_subscription=self.is_subscription,\n            resolver=self.field_resolver,\n            name=self.field_name,\n            description=self.field_description,\n            permission_classes=self.field_permission_classes,\n        )\n\n\ndef _get_field(\n    wrap,\n    *,\n    is_input=False,\n    is_subscription=False,\n    name=None,\n    description=None,\n    check_permission=None\n):\n    name = wrap.__name__\n\n    annotations = typing.get_type_hints(wrap, None, REGISTRY)\n    parameters = inspect.signature(wrap).parameters\n    field_type = get_graphql_type_for_annotation(annotations[\"return\"], name)\n\n    arguments_annotations = {\n        key: value\n        for key, value in annotations.items()\n        if key not in [\"info\", \"return\"]\n    }\n\n    arguments = {\n        to_camel_case(name): get_graphql_type_for_annotation(\n            annotation, name, parameters[name].default != inspect._empty\n        )\n        for name, annotation in arguments_annotations.items()\n    }\n\n    def resolver(source, info, **kwargs):\n        if check_permission:\n            check_permission(source, info, **kwargs)\n\n        kwargs = convert_args(kwargs, arguments_annotations)\n        result = wrap(source, info, **kwargs)\n\n        # graphql-core expects a resolver for an Enum type to return\n        # the enum's *value* (not its name or an instance of the enum).\n        if isinstance(result, enum.Enum):\n            return result.value\n\n        return result\n\n    field_params = {}\n\n    if not is_input:\n        field_params[\"args\"] = arguments\n\n        if is_subscription:\n\n            def _resolve(event, info):\n                if check_permission:\n                    check_permission(event, info)\n\n                return event\n\n            field_params.update({\"subscribe\": resolver, \"resolve\": _resolve})\n        else:\n            field_params.update({\"resolve\": resolver})\n\n    field_params[\"description\"] = description or wrap.__doc__\n\n    FieldType = GraphQLInputField if is_input else GraphQLField\n\n    return FieldType(field_type, **field_params)\n\n\ndef field(\n    wrap=None,\n    *,\n    name=None,\n    description=None,\n    resolver=None,\n    is_input=False,\n    is_subscription=False,\n    permission_classes=None\n):\n    \"\"\"Annotates a method or property as a GraphQL field.\n\n    This is normally used inside a type declaration:\n\n    >>> @strawberry.type:\n    >>> class X:\n    >>>     field_abc: str = strawberry.field(description=\"ABC\")\n\n    >>>     @strawberry.field(description=\"ABC\")\n    >>>     def field_with_resolver(self, info) -> str:\n    >>>         return \"abc\"\n\n    it can be used both as decorator and as a normal function.\n    \"\"\"\n\n    field = strawberry_field(\n        name=name,\n        description=description,\n        resolver=resolver,\n        is_input=is_input,\n        is_subscription=is_subscription,\n        permission_classes=permission_classes,\n    )\n\n    # when calling this with parens we are going to return a strawberry_field\n    # instance, so it can be used as both decorator and function.\n\n    if wrap is None:\n        return field\n\n    # otherwise we run the decorator directly,\n    # when called as @strawberry.field, without parens.\n\n    return field(wrap)\n", "path": "strawberry/field.py"}], "after_files": [{"content": "import dataclasses\nimport enum\nimport inspect\nimport typing\n\nfrom graphql import GraphQLField, GraphQLInputField\n\nfrom .constants import IS_STRAWBERRY_FIELD\nfrom .exceptions import MissingArgumentsAnnotationsError, MissingReturnAnnotationError\nfrom .type_converter import REGISTRY, get_graphql_type_for_annotation\nfrom .utils.arguments import convert_args\nfrom .utils.inspect import get_func_args\nfrom .utils.lazy_property import lazy_property\nfrom .utils.str_converters import to_camel_case\n\n\nclass LazyFieldWrapper:\n    \"\"\"A lazy wrapper for a strawberry field.\n    This allows to use cyclic dependencies in a strawberry fields:\n\n    >>> @strawberry.type\n    >>> class TypeA:\n    >>>     @strawberry.field\n    >>>     def type_b(self, info) -> \"TypeB\":\n    >>>         from .type_b import TypeB\n    >>>         return TypeB()\n    \"\"\"\n\n    def __init__(\n        self,\n        obj,\n        *,\n        is_input=False,\n        is_subscription=False,\n        resolver=None,\n        name=None,\n        description=None,\n        permission_classes=None\n    ):\n        self._wrapped_obj = obj\n        self.is_subscription = is_subscription\n        self.is_input = is_input\n        self.field_name = name\n        self.field_resolver = resolver\n        self.field_description = description\n        self.permission_classes = permission_classes or []\n\n        if callable(self._wrapped_obj):\n            self._check_has_annotations(self._wrapped_obj)\n\n    def _check_has_annotations(self, func):\n        # using annotations without passing from typing.get_type_hints\n        # as we don't need the actually types for the annotations\n        annotations = func.__annotations__\n        name = func.__name__\n\n        if \"return\" not in annotations:\n            raise MissingReturnAnnotationError(name)\n\n        function_arguments = set(get_func_args(func)) - {\"root\", \"self\", \"info\"}\n\n        arguments_annotations = {\n            key: value\n            for key, value in annotations.items()\n            if key not in [\"root\", \"info\", \"return\"]\n        }\n\n        annotated_function_arguments = set(arguments_annotations.keys())\n        arguments_missing_annotations = (\n            function_arguments - annotated_function_arguments\n        )\n\n        if len(arguments_missing_annotations) > 0:\n            raise MissingArgumentsAnnotationsError(name, arguments_missing_annotations)\n\n    def __getattr__(self, attr):\n        if attr in self.__dict__:\n            return getattr(self, attr)\n\n        return getattr(self._wrapped_obj, attr)\n\n    def __call__(self, *args, **kwargs):\n        return self._wrapped_obj(self, *args, **kwargs)\n\n    def _get_permissions(self):\n        \"\"\"\n        Gets all permissions defined in the permission classes\n        >>> strawberry.field(permission_classes=[IsAuthenticated])\n        \"\"\"\n        return (permission() for permission in self.permission_classes)\n\n    def _check_permissions(self, source, info, **kwargs):\n        \"\"\"\n        Checks if the permission should be accepted and\n        raises an exception if not\n        \"\"\"\n        for permission in self._get_permissions():\n            if not permission.has_permission(source, info, **kwargs):\n                message = getattr(permission, \"message\", None)\n                raise PermissionError(message)\n\n    @lazy_property\n    def field(self):\n        return _get_field(\n            self._wrapped_obj,\n            is_input=self.is_input,\n            is_subscription=self.is_subscription,\n            name=self.field_name,\n            description=self.field_description,\n            check_permission=self._check_permissions,\n        )\n\n\nclass strawberry_field(dataclasses.Field):\n    \"\"\"A small wrapper for a field in strawberry.\n\n    You shouldn't be using this directly as this is used internally\n    when using `strawberry.field`.\n\n    This allows to use the following two syntaxes when using the type\n    decorator:\n\n    >>> class X:\n    >>>     field_abc: str = strawberry.field(description=\"ABC\")\n\n    >>> class X:\n    >>>     @strawberry.field(description=\"ABC\")\n    >>>     def field_a(self, info) -> str:\n    >>>         return \"abc\"\n\n    When calling this class as strawberry_field it creates a field\n    that stores metadata (such as field description). In addition\n    to that it also acts as decorator when called as a function,\n    allowing us to us both syntaxes.\n    \"\"\"\n\n    def __init__(\n        self,\n        *,\n        is_input=False,\n        is_subscription=False,\n        resolver=None,\n        name=None,\n        description=None,\n        metadata=None,\n        permission_classes=None\n    ):\n        self.field_name = name\n        self.field_description = description\n        self.field_resolver = resolver\n        self.is_subscription = is_subscription\n        self.is_input = is_input\n        self.field_permission_classes = permission_classes\n\n        super().__init__(\n            # TODO:\n            default=dataclasses.MISSING,\n            default_factory=dataclasses.MISSING,\n            init=resolver is None,\n            repr=True,\n            hash=None,\n            # TODO: this needs to be False when init is False\n            # we could turn it to True when and if we have a default\n            # probably can't be True when passing a resolver\n            compare=is_input,\n            metadata=metadata,\n        )\n\n    def __call__(self, wrap):\n        setattr(wrap, IS_STRAWBERRY_FIELD, True)\n\n        self.field_description = self.field_description or wrap.__doc__\n\n        return LazyFieldWrapper(\n            wrap,\n            is_input=self.is_input,\n            is_subscription=self.is_subscription,\n            resolver=self.field_resolver,\n            name=self.field_name,\n            description=self.field_description,\n            permission_classes=self.field_permission_classes,\n        )\n\n\ndef _get_field(\n    wrap,\n    *,\n    is_input=False,\n    is_subscription=False,\n    name=None,\n    description=None,\n    check_permission=None\n):\n    name = wrap.__name__\n\n    annotations = typing.get_type_hints(wrap, None, REGISTRY)\n    parameters = inspect.signature(wrap).parameters\n    field_type = get_graphql_type_for_annotation(annotations[\"return\"], name)\n\n    arguments_annotations = {\n        key: value\n        for key, value in annotations.items()\n        if key not in [\"info\", \"return\"]\n    }\n\n    arguments = {\n        to_camel_case(name): get_graphql_type_for_annotation(\n            annotation, name, parameters[name].default != inspect._empty\n        )\n        for name, annotation in arguments_annotations.items()\n    }\n\n    def resolver(source, info, **kwargs):\n        if check_permission:\n            check_permission(source, info, **kwargs)\n\n        # the following code allows to omit info and root arguments\n        # by inspecting the original resolver arguments,\n        # if it asks for self, the source will be passed as first argument\n        # if it asks for root, the source it will be passed as kwarg\n        # if it asks for info, the info will be passed as kwarg\n\n        kwargs = convert_args(kwargs, arguments_annotations)\n        function_args = get_func_args(wrap)\n\n        args = []\n\n        if \"self\" in function_args:\n            args.append(wrap)\n\n        if \"root\" in function_args:\n            kwargs[\"root\"] = source\n\n        if \"info\" in function_args:\n            kwargs[\"info\"] = info\n\n        result = wrap(*args, **kwargs)\n\n        # graphql-core expects a resolver for an Enum type to return\n        # the enum's *value* (not its name or an instance of the enum).\n        if isinstance(result, enum.Enum):\n            return result.value\n\n        return result\n\n    field_params = {}\n\n    if not is_input:\n        field_params[\"args\"] = arguments\n\n        if is_subscription:\n\n            def _resolve(event, info):\n                if check_permission:\n                    check_permission(event, info)\n\n                return event\n\n            field_params.update({\"subscribe\": resolver, \"resolve\": _resolve})\n        else:\n            field_params.update({\"resolve\": resolver})\n\n    field_params[\"description\"] = description or wrap.__doc__\n\n    FieldType = GraphQLInputField if is_input else GraphQLField\n\n    return FieldType(field_type, **field_params)\n\n\ndef field(\n    wrap=None,\n    *,\n    name=None,\n    description=None,\n    resolver=None,\n    is_input=False,\n    is_subscription=False,\n    permission_classes=None\n):\n    \"\"\"Annotates a method or property as a GraphQL field.\n\n    This is normally used inside a type declaration:\n\n    >>> @strawberry.type:\n    >>> class X:\n    >>>     field_abc: str = strawberry.field(description=\"ABC\")\n\n    >>>     @strawberry.field(description=\"ABC\")\n    >>>     def field_with_resolver(self, info) -> str:\n    >>>         return \"abc\"\n\n    it can be used both as decorator and as a normal function.\n    \"\"\"\n\n    field = strawberry_field(\n        name=name,\n        description=description,\n        resolver=resolver,\n        is_input=is_input,\n        is_subscription=is_subscription,\n        permission_classes=permission_classes,\n    )\n\n    # when calling this with parens we are going to return a strawberry_field\n    # instance, so it can be used as both decorator and function.\n\n    if wrap is None:\n        return field\n\n    # otherwise we run the decorator directly,\n    # when called as @strawberry.field, without parens.\n\n    return field(wrap)\n", "path": "strawberry/field.py"}]}