strawberry-graphql 0.275.7__py3-none-any.whl → 0.284.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of strawberry-graphql might be problematic. Click here for more details.

Files changed (161) hide show
  1. strawberry/__init__.py +2 -0
  2. strawberry/aiohttp/test/client.py +8 -15
  3. strawberry/aiohttp/views.py +15 -64
  4. strawberry/annotation.py +70 -25
  5. strawberry/asgi/__init__.py +22 -56
  6. strawberry/asgi/test/client.py +6 -6
  7. strawberry/chalice/views.py +13 -79
  8. strawberry/channels/handlers/base.py +7 -8
  9. strawberry/channels/handlers/http_handler.py +50 -32
  10. strawberry/channels/handlers/ws_handler.py +12 -14
  11. strawberry/channels/router.py +3 -4
  12. strawberry/channels/testing.py +7 -9
  13. strawberry/cli/__init__.py +7 -6
  14. strawberry/cli/commands/codegen.py +7 -7
  15. strawberry/cli/commands/dev.py +72 -0
  16. strawberry/cli/commands/schema_codegen.py +1 -2
  17. strawberry/cli/commands/server.py +3 -44
  18. strawberry/cli/commands/upgrade/__init__.py +3 -3
  19. strawberry/cli/commands/upgrade/_run_codemod.py +2 -2
  20. strawberry/cli/constants.py +1 -2
  21. strawberry/cli/{debug_server.py → dev_server.py} +3 -7
  22. strawberry/codegen/plugins/print_operation.py +2 -2
  23. strawberry/codegen/plugins/python.py +2 -2
  24. strawberry/codegen/query_codegen.py +20 -30
  25. strawberry/codegen/types.py +32 -32
  26. strawberry/codemods/__init__.py +9 -0
  27. strawberry/codemods/annotated_unions.py +2 -2
  28. strawberry/codemods/maybe_optional.py +118 -0
  29. strawberry/dataloader.py +28 -24
  30. strawberry/directive.py +6 -7
  31. strawberry/django/test/client.py +3 -3
  32. strawberry/django/views.py +21 -91
  33. strawberry/exceptions/__init__.py +4 -4
  34. strawberry/exceptions/conflicting_arguments.py +2 -2
  35. strawberry/exceptions/duplicated_type_name.py +4 -4
  36. strawberry/exceptions/exception.py +3 -3
  37. strawberry/exceptions/handler.py +8 -7
  38. strawberry/exceptions/invalid_argument_type.py +2 -2
  39. strawberry/exceptions/invalid_superclass_interface.py +2 -2
  40. strawberry/exceptions/invalid_union_type.py +4 -4
  41. strawberry/exceptions/missing_arguments_annotations.py +2 -2
  42. strawberry/exceptions/missing_dependencies.py +2 -4
  43. strawberry/exceptions/missing_field_annotation.py +2 -2
  44. strawberry/exceptions/missing_return_annotation.py +2 -2
  45. strawberry/exceptions/object_is_not_a_class.py +2 -2
  46. strawberry/exceptions/object_is_not_an_enum.py +2 -2
  47. strawberry/exceptions/permission_fail_silently_requires_optional.py +2 -2
  48. strawberry/exceptions/private_strawberry_field.py +2 -2
  49. strawberry/exceptions/scalar_already_registered.py +2 -2
  50. strawberry/exceptions/syntax.py +3 -3
  51. strawberry/exceptions/unresolved_field_type.py +2 -2
  52. strawberry/exceptions/utils/source_finder.py +25 -25
  53. strawberry/experimental/pydantic/_compat.py +8 -7
  54. strawberry/experimental/pydantic/conversion.py +2 -2
  55. strawberry/experimental/pydantic/conversion_types.py +2 -2
  56. strawberry/experimental/pydantic/error_type.py +10 -12
  57. strawberry/experimental/pydantic/fields.py +9 -15
  58. strawberry/experimental/pydantic/object_type.py +17 -25
  59. strawberry/experimental/pydantic/utils.py +1 -2
  60. strawberry/ext/mypy_plugin.py +12 -14
  61. strawberry/extensions/base_extension.py +2 -1
  62. strawberry/extensions/context.py +13 -18
  63. strawberry/extensions/directives.py +9 -3
  64. strawberry/extensions/field_extension.py +4 -4
  65. strawberry/extensions/mask_errors.py +24 -13
  66. strawberry/extensions/max_aliases.py +1 -3
  67. strawberry/extensions/parser_cache.py +1 -2
  68. strawberry/extensions/query_depth_limiter.py +18 -14
  69. strawberry/extensions/runner.py +2 -2
  70. strawberry/extensions/tracing/apollo.py +3 -3
  71. strawberry/extensions/tracing/datadog.py +3 -3
  72. strawberry/extensions/tracing/opentelemetry.py +6 -8
  73. strawberry/extensions/tracing/utils.py +3 -1
  74. strawberry/extensions/utils.py +2 -2
  75. strawberry/extensions/validation_cache.py +2 -3
  76. strawberry/fastapi/context.py +6 -6
  77. strawberry/fastapi/router.py +43 -42
  78. strawberry/federation/argument.py +4 -5
  79. strawberry/federation/enum.py +18 -21
  80. strawberry/federation/field.py +94 -97
  81. strawberry/federation/object_type.py +56 -58
  82. strawberry/federation/scalar.py +27 -35
  83. strawberry/federation/schema.py +15 -16
  84. strawberry/federation/schema_directive.py +7 -6
  85. strawberry/federation/schema_directives.py +11 -11
  86. strawberry/federation/union.py +4 -4
  87. strawberry/flask/views.py +16 -85
  88. strawberry/http/__init__.py +30 -20
  89. strawberry/http/async_base_view.py +208 -89
  90. strawberry/http/base.py +28 -11
  91. strawberry/http/exceptions.py +5 -7
  92. strawberry/http/ides.py +2 -3
  93. strawberry/http/sync_base_view.py +115 -69
  94. strawberry/http/types.py +3 -3
  95. strawberry/litestar/controller.py +43 -77
  96. strawberry/permission.py +4 -6
  97. strawberry/printer/ast_from_value.py +3 -5
  98. strawberry/printer/printer.py +18 -15
  99. strawberry/quart/views.py +16 -48
  100. strawberry/relay/exceptions.py +4 -4
  101. strawberry/relay/fields.py +33 -32
  102. strawberry/relay/types.py +32 -35
  103. strawberry/relay/utils.py +11 -23
  104. strawberry/resolvers.py +2 -1
  105. strawberry/sanic/context.py +1 -0
  106. strawberry/sanic/utils.py +3 -3
  107. strawberry/sanic/views.py +15 -54
  108. strawberry/scalars.py +2 -2
  109. strawberry/schema/_graphql_core.py +55 -0
  110. strawberry/schema/base.py +32 -33
  111. strawberry/schema/compat.py +9 -9
  112. strawberry/schema/config.py +10 -1
  113. strawberry/schema/exceptions.py +1 -3
  114. strawberry/schema/name_converter.py +9 -8
  115. strawberry/schema/schema.py +133 -100
  116. strawberry/schema/schema_converter.py +96 -58
  117. strawberry/schema/types/base_scalars.py +1 -1
  118. strawberry/schema/types/concrete_type.py +5 -5
  119. strawberry/schema/validation_rules/maybe_null.py +136 -0
  120. strawberry/schema_codegen/__init__.py +3 -3
  121. strawberry/schema_directive.py +7 -6
  122. strawberry/static/graphiql.html +5 -5
  123. strawberry/streamable.py +35 -0
  124. strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +5 -16
  125. strawberry/subscriptions/protocols/graphql_transport_ws/types.py +20 -20
  126. strawberry/subscriptions/protocols/graphql_ws/handlers.py +5 -12
  127. strawberry/subscriptions/protocols/graphql_ws/types.py +14 -14
  128. strawberry/test/client.py +18 -18
  129. strawberry/tools/create_type.py +2 -3
  130. strawberry/types/arguments.py +41 -28
  131. strawberry/types/auto.py +3 -4
  132. strawberry/types/base.py +25 -27
  133. strawberry/types/enum.py +22 -25
  134. strawberry/types/execution.py +21 -16
  135. strawberry/types/field.py +109 -130
  136. strawberry/types/fields/resolver.py +19 -21
  137. strawberry/types/info.py +5 -11
  138. strawberry/types/lazy_type.py +2 -3
  139. strawberry/types/maybe.py +12 -3
  140. strawberry/types/mutation.py +115 -118
  141. strawberry/types/nodes.py +2 -2
  142. strawberry/types/object_type.py +43 -63
  143. strawberry/types/scalar.py +37 -43
  144. strawberry/types/union.py +12 -14
  145. strawberry/utils/aio.py +12 -9
  146. strawberry/utils/await_maybe.py +3 -3
  147. strawberry/utils/deprecations.py +2 -2
  148. strawberry/utils/importer.py +1 -2
  149. strawberry/utils/inspect.py +4 -6
  150. strawberry/utils/logging.py +2 -2
  151. strawberry/utils/operation.py +4 -4
  152. strawberry/utils/typing.py +18 -83
  153. {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info}/METADATA +14 -8
  154. strawberry_graphql-0.284.3.dist-info/RECORD +243 -0
  155. {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info}/WHEEL +1 -1
  156. strawberry/utils/dataclasses.py +0 -37
  157. strawberry/utils/debug.py +0 -46
  158. strawberry/utils/graphql_lexer.py +0 -35
  159. strawberry_graphql-0.275.7.dist-info/RECORD +0 -241
  160. {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info}/entry_points.txt +0 -0
  161. {strawberry_graphql-0.275.7.dist-info → strawberry_graphql-0.284.3.dist-info/licenses}/LICENSE +0 -0
strawberry/types/enum.py CHANGED
@@ -1,12 +1,9 @@
1
1
  import dataclasses
2
- from collections.abc import Iterable, Mapping
2
+ from collections.abc import Callable, Iterable, Mapping
3
3
  from enum import EnumMeta
4
4
  from typing import (
5
5
  Any,
6
- Callable,
7
- Optional,
8
6
  TypeVar,
9
- Union,
10
7
  overload,
11
8
  )
12
9
 
@@ -18,9 +15,9 @@ from strawberry.types.base import StrawberryType
18
15
  class EnumValue:
19
16
  name: str
20
17
  value: Any
21
- deprecation_reason: Optional[str] = None
18
+ deprecation_reason: str | None = None
22
19
  directives: Iterable[object] = ()
23
- description: Optional[str] = None
20
+ description: str | None = None
24
21
 
25
22
 
26
23
  @dataclasses.dataclass
@@ -28,7 +25,7 @@ class EnumDefinition(StrawberryType):
28
25
  wrapped_cls: EnumMeta
29
26
  name: str
30
27
  values: list[EnumValue]
31
- description: Optional[str]
28
+ description: str | None
32
29
  directives: Iterable[object] = ()
33
30
 
34
31
  def __hash__(self) -> int:
@@ -36,8 +33,8 @@ class EnumDefinition(StrawberryType):
36
33
  return hash(self.name)
37
34
 
38
35
  def copy_with(
39
- self, type_var_map: Mapping[str, Union[StrawberryType, type]]
40
- ) -> Union[StrawberryType, type]:
36
+ self, type_var_map: Mapping[str, StrawberryType | type]
37
+ ) -> StrawberryType | type:
41
38
  # enum don't support type parameters, so we can safely return self
42
39
  return self
43
40
 
@@ -54,10 +51,10 @@ class EnumDefinition(StrawberryType):
54
51
  @dataclasses.dataclass
55
52
  class EnumValueDefinition:
56
53
  value: Any
57
- graphql_name: Optional[str] = None
58
- deprecation_reason: Optional[str] = None
54
+ graphql_name: str | None = None
55
+ deprecation_reason: str | None = None
59
56
  directives: Iterable[object] = ()
60
- description: Optional[str] = None
57
+ description: str | None = None
61
58
 
62
59
  def __int__(self) -> int:
63
60
  return self.value
@@ -65,10 +62,10 @@ class EnumValueDefinition:
65
62
 
66
63
  def enum_value(
67
64
  value: Any,
68
- name: Optional[str] = None,
69
- deprecation_reason: Optional[str] = None,
65
+ name: str | None = None,
66
+ deprecation_reason: str | None = None,
70
67
  directives: Iterable[object] = (),
71
- description: Optional[str] = None,
68
+ description: str | None = None,
72
69
  ) -> EnumValueDefinition:
73
70
  """Function to customise an enum value, for example to add a description or deprecation reason.
74
71
 
@@ -109,8 +106,8 @@ EnumType = TypeVar("EnumType", bound=EnumMeta)
109
106
 
110
107
  def _process_enum(
111
108
  cls: EnumType,
112
- name: Optional[str] = None,
113
- description: Optional[str] = None,
109
+ name: str | None = None,
110
+ description: str | None = None,
114
111
  directives: Iterable[object] = (),
115
112
  ) -> EnumType:
116
113
  if not isinstance(cls, EnumMeta):
@@ -166,8 +163,8 @@ def _process_enum(
166
163
  def enum(
167
164
  cls: EnumType,
168
165
  *,
169
- name: Optional[str] = None,
170
- description: Optional[str] = None,
166
+ name: str | None = None,
167
+ description: str | None = None,
171
168
  directives: Iterable[object] = (),
172
169
  ) -> EnumType: ...
173
170
 
@@ -176,19 +173,19 @@ def enum(
176
173
  def enum(
177
174
  cls: None = None,
178
175
  *,
179
- name: Optional[str] = None,
180
- description: Optional[str] = None,
176
+ name: str | None = None,
177
+ description: str | None = None,
181
178
  directives: Iterable[object] = (),
182
179
  ) -> Callable[[EnumType], EnumType]: ...
183
180
 
184
181
 
185
182
  def enum(
186
- cls: Optional[EnumType] = None,
183
+ cls: EnumType | None = None,
187
184
  *,
188
- name: Optional[str] = None,
189
- description: Optional[str] = None,
185
+ name: str | None = None,
186
+ description: str | None = None,
190
187
  directives: Iterable[object] = (),
191
- ) -> Union[EnumType, Callable[[EnumType], EnumType]]:
188
+ ) -> EnumType | Callable[[EnumType], EnumType]:
192
189
  """Annotates an Enum class a GraphQL enum.
193
190
 
194
191
  GraphQL enums only have names, while Python enums have names and values,
@@ -4,10 +4,9 @@ import dataclasses
4
4
  from typing import (
5
5
  TYPE_CHECKING,
6
6
  Any,
7
- Optional,
8
7
  runtime_checkable,
9
8
  )
10
- from typing_extensions import Protocol, TypedDict
9
+ from typing_extensions import Protocol, TypedDict, deprecated
11
10
 
12
11
  from graphql import specified_rules
13
12
 
@@ -18,47 +17,47 @@ if TYPE_CHECKING:
18
17
  from typing_extensions import NotRequired
19
18
 
20
19
  from graphql import ASTValidationRule
21
- from graphql import ExecutionResult as GraphQLExecutionResult
22
20
  from graphql.error.graphql_error import GraphQLError
23
21
  from graphql.language import DocumentNode, OperationDefinitionNode
24
22
 
25
23
  from strawberry.schema import Schema
24
+ from strawberry.schema._graphql_core import GraphQLExecutionResult
26
25
 
27
26
  from .graphql import OperationType
28
27
 
29
28
 
30
29
  @dataclasses.dataclass
31
30
  class ExecutionContext:
32
- query: Optional[str]
31
+ query: str | None
33
32
  schema: Schema
34
33
  allowed_operations: Iterable[OperationType]
35
34
  context: Any = None
36
- variables: Optional[dict[str, Any]] = None
35
+ variables: dict[str, Any] | None = None
37
36
  parse_options: ParseOptions = dataclasses.field(
38
37
  default_factory=lambda: ParseOptions()
39
38
  )
40
- root_value: Optional[Any] = None
39
+ root_value: Any | None = None
41
40
  validation_rules: tuple[type[ASTValidationRule], ...] = dataclasses.field(
42
41
  default_factory=lambda: tuple(specified_rules)
43
42
  )
44
43
 
45
44
  # The operation name that is provided by the request
46
- provided_operation_name: dataclasses.InitVar[Optional[str]] = None
45
+ provided_operation_name: dataclasses.InitVar[str | None] = None
47
46
 
48
47
  # Values that get populated during the GraphQL execution so that they can be
49
48
  # accessed by extensions
50
- graphql_document: Optional[DocumentNode] = None
51
- errors: Optional[list[GraphQLError]] = None
52
- result: Optional[GraphQLExecutionResult] = None
49
+ graphql_document: DocumentNode | None = None
50
+ pre_execution_errors: list[GraphQLError] | None = None
51
+ result: GraphQLExecutionResult | None = None
53
52
  extensions_results: dict[str, Any] = dataclasses.field(default_factory=dict)
54
53
 
55
- operation_extensions: Optional[dict[str, Any]] = None
54
+ operation_extensions: dict[str, Any] | None = None
56
55
 
57
56
  def __post_init__(self, provided_operation_name: str | None) -> None:
58
57
  self._provided_operation_name = provided_operation_name
59
58
 
60
59
  @property
61
- def operation_name(self) -> Optional[str]:
60
+ def operation_name(self) -> str | None:
62
61
  if self._provided_operation_name is not None:
63
62
  return self._provided_operation_name
64
63
 
@@ -79,19 +78,25 @@ class ExecutionContext:
79
78
 
80
79
  return get_operation_type(graphql_document, self.operation_name)
81
80
 
82
- def _get_first_operation(self) -> Optional[OperationDefinitionNode]:
81
+ def _get_first_operation(self) -> OperationDefinitionNode | None:
83
82
  graphql_document = self.graphql_document
84
83
  if not graphql_document:
85
84
  return None
86
85
 
87
86
  return get_first_operation(graphql_document)
88
87
 
88
+ @property
89
+ @deprecated("Use 'pre_execution_errors' instead")
90
+ def errors(self) -> list[GraphQLError] | None:
91
+ """Deprecated: Use pre_execution_errors instead."""
92
+ return self.pre_execution_errors
93
+
89
94
 
90
95
  @dataclasses.dataclass
91
96
  class ExecutionResult:
92
- data: Optional[dict[str, Any]]
93
- errors: Optional[list[GraphQLError]]
94
- extensions: Optional[dict[str, Any]] = None
97
+ data: dict[str, Any] | None
98
+ errors: list[GraphQLError] | None
99
+ extensions: dict[str, Any] | None = None
95
100
 
96
101
 
97
102
  @dataclasses.dataclass
strawberry/types/field.py CHANGED
@@ -4,16 +4,15 @@ import contextlib
4
4
  import copy
5
5
  import dataclasses
6
6
  import sys
7
- from collections.abc import Awaitable, Coroutine, Mapping, Sequence
7
+ from collections.abc import Awaitable, Callable, Coroutine, Mapping, Sequence
8
8
  from functools import cached_property
9
9
  from typing import (
10
10
  TYPE_CHECKING,
11
11
  Any,
12
- Callable,
13
- Optional,
12
+ NoReturn,
13
+ TypeAlias,
14
14
  TypeVar,
15
15
  Union,
16
- cast,
17
16
  overload,
18
17
  )
19
18
 
@@ -30,7 +29,8 @@ from .fields.resolver import StrawberryResolver
30
29
 
31
30
  if TYPE_CHECKING:
32
31
  import builtins
33
- from typing_extensions import Literal, Self
32
+ from typing import Literal
33
+ from typing_extensions import Self
34
34
 
35
35
  from strawberry.extensions.field_extension import FieldExtension
36
36
  from strawberry.permission import BasePermission
@@ -40,24 +40,31 @@ if TYPE_CHECKING:
40
40
 
41
41
  T = TypeVar("T")
42
42
 
43
- _RESOLVER_TYPE_SYNC = Union[
43
+ _RESOLVER_TYPE_SYNC: TypeAlias = Union[
44
44
  StrawberryResolver[T],
45
45
  Callable[..., T],
46
46
  "staticmethod[Any, T]",
47
47
  "classmethod[Any, Any, T]",
48
48
  ]
49
49
 
50
- _RESOLVER_TYPE_ASYNC = Union[
51
- Callable[..., Coroutine[Any, Any, T]],
52
- Callable[..., Awaitable[T]],
53
- ]
50
+ _RESOLVER_TYPE_ASYNC: TypeAlias = (
51
+ Callable[..., Coroutine[Any, Any, T]] | Callable[..., Awaitable[T]]
52
+ )
54
53
 
55
- _RESOLVER_TYPE = Union[_RESOLVER_TYPE_SYNC[T], _RESOLVER_TYPE_ASYNC[T]]
54
+ _RESOLVER_TYPE: TypeAlias = _RESOLVER_TYPE_SYNC[T] | _RESOLVER_TYPE_ASYNC[T]
56
55
 
57
- UNRESOLVED = object()
58
56
 
57
+ class UNRESOLVED:
58
+ def __new__(cls) -> NoReturn:
59
+ raise TypeError("UNRESOLVED is a sentinel and cannot be instantiated.")
59
60
 
60
- def _is_generic(resolver_type: Union[StrawberryType, type]) -> bool:
61
+
62
+ FieldType: TypeAlias = (
63
+ StrawberryType | type[WithStrawberryObjectDefinition | UNRESOLVED]
64
+ )
65
+
66
+
67
+ def _is_generic(resolver_type: StrawberryType | type) -> bool:
61
68
  """Returns True if `resolver_type` is generic else False."""
62
69
  if isinstance(resolver_type, StrawberryType):
63
70
  return resolver_type.is_graphql_generic
@@ -70,34 +77,36 @@ def _is_generic(resolver_type: Union[StrawberryType, type]) -> bool:
70
77
 
71
78
 
72
79
  class StrawberryField(dataclasses.Field):
73
- type_annotation: Optional[StrawberryAnnotation]
80
+ type_annotation: StrawberryAnnotation | None
74
81
  default_resolver: Callable[[Any, str], object] = getattr
75
82
 
76
83
  def __init__(
77
84
  self,
78
- python_name: Optional[str] = None,
79
- graphql_name: Optional[str] = None,
80
- type_annotation: Optional[StrawberryAnnotation] = None,
81
- origin: Optional[Union[type, Callable, staticmethod, classmethod]] = None,
85
+ python_name: str | None = None,
86
+ graphql_name: str | None = None,
87
+ type_annotation: StrawberryAnnotation | None = None,
88
+ origin: type | Callable | staticmethod | classmethod | None = None,
82
89
  is_subscription: bool = False,
83
- description: Optional[str] = None,
84
- base_resolver: Optional[StrawberryResolver] = None,
90
+ description: str | None = None,
91
+ base_resolver: StrawberryResolver | None = None,
85
92
  permission_classes: list[type[BasePermission]] = (), # type: ignore
86
93
  default: object = dataclasses.MISSING,
87
- default_factory: Union[Callable[[], Any], object] = dataclasses.MISSING,
88
- metadata: Optional[Mapping[Any, Any]] = None,
89
- deprecation_reason: Optional[str] = None,
94
+ default_factory: Callable[[], Any] | object = dataclasses.MISSING,
95
+ metadata: Mapping[Any, Any] | None = None,
96
+ deprecation_reason: str | None = None,
90
97
  directives: Sequence[object] = (),
91
98
  extensions: list[FieldExtension] = (), # type: ignore
92
99
  ) -> None:
93
100
  # basic fields are fields with no provided resolver
94
101
  is_basic_field = not base_resolver
95
102
 
96
- kwargs: Any = {}
103
+ kwargs: Any = {
104
+ "kw_only": True,
105
+ }
97
106
 
98
- # kw_only was added to python 3.10 and it is required
99
- if sys.version_info >= (3, 10):
100
- kwargs["kw_only"] = dataclasses.MISSING
107
+ # doc was added to python 3.14 and it is required
108
+ if sys.version_info >= (3, 14):
109
+ kwargs["doc"] = None
101
110
 
102
111
  super().__init__(
103
112
  default=default,
@@ -116,11 +125,11 @@ class StrawberryField(dataclasses.Field):
116
125
 
117
126
  self.type_annotation = type_annotation
118
127
 
119
- self.description: Optional[str] = description
128
+ self.description: str | None = description
120
129
  self.origin = origin
121
130
 
122
- self._arguments: Optional[list[StrawberryArgument]] = None
123
- self._base_resolver: Optional[StrawberryResolver] = None
131
+ self._arguments: list[StrawberryArgument] | None = None
132
+ self._base_resolver: StrawberryResolver | None = None
124
133
  if base_resolver is not None:
125
134
  self.base_resolver = base_resolver
126
135
 
@@ -212,8 +221,8 @@ class StrawberryField(dataclasses.Field):
212
221
  return self
213
222
 
214
223
  def get_result(
215
- self, source: Any, info: Optional[Info], args: list[Any], kwargs: Any
216
- ) -> Union[Awaitable[Any], Any]:
224
+ self, source: Any, info: Info | None, args: list[Any], kwargs: Any
225
+ ) -> Awaitable[Any] | Any:
217
226
  """Calls the resolver defined for the StrawberryField.
218
227
 
219
228
  If the field doesn't have a resolver defined we default
@@ -255,7 +264,7 @@ class StrawberryField(dataclasses.Field):
255
264
  else _is_generic(self.type)
256
265
  )
257
266
 
258
- def _python_name(self) -> Optional[str]:
267
+ def _python_name(self) -> str | None:
259
268
  if self.name:
260
269
  return self.name
261
270
 
@@ -270,7 +279,7 @@ class StrawberryField(dataclasses.Field):
270
279
  python_name: str = property(_python_name, _set_python_name) # type: ignore[assignment]
271
280
 
272
281
  @property
273
- def base_resolver(self) -> Optional[StrawberryResolver]:
282
+ def base_resolver(self) -> StrawberryResolver | None:
274
283
  return self._base_resolver
275
284
 
276
285
  @base_resolver.setter
@@ -293,14 +302,8 @@ class StrawberryField(dataclasses.Field):
293
302
  # removed.
294
303
  _ = resolver.arguments
295
304
 
296
- @property # type: ignore
297
- def type(
298
- self,
299
- ) -> Union[ # type: ignore [valid-type]
300
- StrawberryType,
301
- type[WithStrawberryObjectDefinition],
302
- Literal[UNRESOLVED],
303
- ]:
305
+ @property
306
+ def type(self) -> FieldType:
304
307
  return self.resolve_type()
305
308
 
306
309
  @type.setter
@@ -330,15 +333,11 @@ class StrawberryField(dataclasses.Field):
330
333
  def resolve_type(
331
334
  self,
332
335
  *,
333
- type_definition: Optional[StrawberryObjectDefinition] = None,
334
- ) -> Union[ # type: ignore [valid-type]
335
- StrawberryType,
336
- type[WithStrawberryObjectDefinition],
337
- Literal[UNRESOLVED],
338
- ]:
336
+ type_definition: StrawberryObjectDefinition | None = None,
337
+ ) -> FieldType:
339
338
  # We return UNRESOLVED by default, which means this case will raise a
340
339
  # MissingReturnAnnotationError exception in _check_field_annotations
341
- resolved = UNRESOLVED
340
+ resolved: FieldType = UNRESOLVED # type: ignore[assignment]
342
341
 
343
342
  # We are catching NameError because dataclasses tries to fetch the type
344
343
  # of the field from the class before the class is fully defined.
@@ -348,7 +347,7 @@ class StrawberryField(dataclasses.Field):
348
347
  with contextlib.suppress(NameError):
349
348
  # Prioritise the field type over the resolver return type
350
349
  if self.type_annotation is not None:
351
- resolved = self.type_annotation.resolve()
350
+ resolved = self.type_annotation.resolve(type_definition=type_definition)
352
351
  elif self.base_resolver is not None and self.base_resolver.type is not None:
353
352
  # Handle unannotated functions (such as lambdas)
354
353
  # Generics will raise MissingTypesForGenericError later
@@ -356,36 +355,16 @@ class StrawberryField(dataclasses.Field):
356
355
  # which is the same behaviour as having no type information.
357
356
  resolved = self.base_resolver.type
358
357
 
359
- # If this is a generic field, try to resolve it using its origin's
360
- # specialized type_var_map
361
- # TODO: should we check arguments here too?
362
- if _is_generic(resolved): # type: ignore
363
- specialized_type_var_map = (
364
- type_definition and type_definition.specialized_type_var_map
365
- )
366
- if specialized_type_var_map and isinstance(resolved, StrawberryType):
367
- resolved = resolved.copy_with(specialized_type_var_map)
368
-
369
- # If the field is still generic, try to resolve it from the type_definition
370
- # that is asking for it.
371
- if (
372
- _is_generic(cast("Union[StrawberryType, type]", resolved))
373
- and type_definition is not None
374
- and type_definition.type_var_map
375
- and isinstance(resolved, StrawberryType)
376
- ):
377
- resolved = resolved.copy_with(type_definition.type_var_map)
378
-
379
358
  return resolved
380
359
 
381
360
  def copy_with(
382
- self, type_var_map: Mapping[str, Union[StrawberryType, builtins.type]]
361
+ self, type_var_map: Mapping[str, StrawberryType | builtins.type]
383
362
  ) -> Self:
384
363
  new_field = copy.copy(self)
385
364
 
386
- override_type: Optional[
387
- Union[StrawberryType, type[WithStrawberryObjectDefinition]]
388
- ] = None
365
+ override_type: StrawberryType | type[WithStrawberryObjectDefinition] | None = (
366
+ None
367
+ )
389
368
  type_ = self.resolve_type()
390
369
  if has_object_definition(type_):
391
370
  type_definition = type_.__strawberry_definition__
@@ -426,18 +405,18 @@ class StrawberryField(dataclasses.Field):
426
405
  def field(
427
406
  *,
428
407
  resolver: _RESOLVER_TYPE_ASYNC[T],
429
- name: Optional[str] = None,
408
+ name: str | None = None,
430
409
  is_subscription: bool = False,
431
- description: Optional[str] = None,
410
+ description: str | None = None,
432
411
  init: Literal[False] = False,
433
- permission_classes: Optional[list[type[BasePermission]]] = None,
434
- deprecation_reason: Optional[str] = None,
412
+ permission_classes: list[type[BasePermission]] | None = None,
413
+ deprecation_reason: str | None = None,
435
414
  default: Any = dataclasses.MISSING,
436
- default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
437
- metadata: Optional[Mapping[Any, Any]] = None,
438
- directives: Optional[Sequence[object]] = (),
439
- extensions: Optional[list[FieldExtension]] = None,
440
- graphql_type: Optional[Any] = None,
415
+ default_factory: Callable[..., object] | object = dataclasses.MISSING,
416
+ metadata: Mapping[Any, Any] | None = None,
417
+ directives: Sequence[object] | None = (),
418
+ extensions: list[FieldExtension] | None = None,
419
+ graphql_type: Any | None = None,
441
420
  ) -> T: ...
442
421
 
443
422
 
@@ -445,36 +424,36 @@ def field(
445
424
  def field(
446
425
  *,
447
426
  resolver: _RESOLVER_TYPE_SYNC[T],
448
- name: Optional[str] = None,
427
+ name: str | None = None,
449
428
  is_subscription: bool = False,
450
- description: Optional[str] = None,
429
+ description: str | None = None,
451
430
  init: Literal[False] = False,
452
- permission_classes: Optional[list[type[BasePermission]]] = None,
453
- deprecation_reason: Optional[str] = None,
431
+ permission_classes: list[type[BasePermission]] | None = None,
432
+ deprecation_reason: str | None = None,
454
433
  default: Any = dataclasses.MISSING,
455
- default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
456
- metadata: Optional[Mapping[Any, Any]] = None,
457
- directives: Optional[Sequence[object]] = (),
458
- extensions: Optional[list[FieldExtension]] = None,
459
- graphql_type: Optional[Any] = None,
434
+ default_factory: Callable[..., object] | object = dataclasses.MISSING,
435
+ metadata: Mapping[Any, Any] | None = None,
436
+ directives: Sequence[object] | None = (),
437
+ extensions: list[FieldExtension] | None = None,
438
+ graphql_type: Any | None = None,
460
439
  ) -> T: ...
461
440
 
462
441
 
463
442
  @overload
464
443
  def field(
465
444
  *,
466
- name: Optional[str] = None,
445
+ name: str | None = None,
467
446
  is_subscription: bool = False,
468
- description: Optional[str] = None,
447
+ description: str | None = None,
469
448
  init: Literal[True] = True,
470
- permission_classes: Optional[list[type[BasePermission]]] = None,
471
- deprecation_reason: Optional[str] = None,
449
+ permission_classes: list[type[BasePermission]] | None = None,
450
+ deprecation_reason: str | None = None,
472
451
  default: Any = dataclasses.MISSING,
473
- default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
474
- metadata: Optional[Mapping[Any, Any]] = None,
475
- directives: Optional[Sequence[object]] = (),
476
- extensions: Optional[list[FieldExtension]] = None,
477
- graphql_type: Optional[Any] = None,
452
+ default_factory: Callable[..., object] | object = dataclasses.MISSING,
453
+ metadata: Mapping[Any, Any] | None = None,
454
+ directives: Sequence[object] | None = (),
455
+ extensions: list[FieldExtension] | None = None,
456
+ graphql_type: Any | None = None,
478
457
  ) -> Any: ...
479
458
 
480
459
 
@@ -482,17 +461,17 @@ def field(
482
461
  def field(
483
462
  resolver: _RESOLVER_TYPE_ASYNC[T],
484
463
  *,
485
- name: Optional[str] = None,
464
+ name: str | None = None,
486
465
  is_subscription: bool = False,
487
- description: Optional[str] = None,
488
- permission_classes: Optional[list[type[BasePermission]]] = None,
489
- deprecation_reason: Optional[str] = None,
466
+ description: str | None = None,
467
+ permission_classes: list[type[BasePermission]] | None = None,
468
+ deprecation_reason: str | None = None,
490
469
  default: Any = dataclasses.MISSING,
491
- default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
492
- metadata: Optional[Mapping[Any, Any]] = None,
493
- directives: Optional[Sequence[object]] = (),
494
- extensions: Optional[list[FieldExtension]] = None,
495
- graphql_type: Optional[Any] = None,
470
+ default_factory: Callable[..., object] | object = dataclasses.MISSING,
471
+ metadata: Mapping[Any, Any] | None = None,
472
+ directives: Sequence[object] | None = (),
473
+ extensions: list[FieldExtension] | None = None,
474
+ graphql_type: Any | None = None,
496
475
  ) -> StrawberryField: ...
497
476
 
498
477
 
@@ -500,38 +479,38 @@ def field(
500
479
  def field(
501
480
  resolver: _RESOLVER_TYPE_SYNC[T],
502
481
  *,
503
- name: Optional[str] = None,
482
+ name: str | None = None,
504
483
  is_subscription: bool = False,
505
- description: Optional[str] = None,
506
- permission_classes: Optional[list[type[BasePermission]]] = None,
507
- deprecation_reason: Optional[str] = None,
484
+ description: str | None = None,
485
+ permission_classes: list[type[BasePermission]] | None = None,
486
+ deprecation_reason: str | None = None,
508
487
  default: Any = dataclasses.MISSING,
509
- default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
510
- metadata: Optional[Mapping[Any, Any]] = None,
511
- directives: Optional[Sequence[object]] = (),
512
- extensions: Optional[list[FieldExtension]] = None,
513
- graphql_type: Optional[Any] = None,
488
+ default_factory: Callable[..., object] | object = dataclasses.MISSING,
489
+ metadata: Mapping[Any, Any] | None = None,
490
+ directives: Sequence[object] | None = (),
491
+ extensions: list[FieldExtension] | None = None,
492
+ graphql_type: Any | None = None,
514
493
  ) -> StrawberryField: ...
515
494
 
516
495
 
517
496
  def field(
518
- resolver: Optional[_RESOLVER_TYPE[Any]] = None,
497
+ resolver: _RESOLVER_TYPE[Any] | None = None,
519
498
  *,
520
- name: Optional[str] = None,
499
+ name: str | None = None,
521
500
  is_subscription: bool = False,
522
- description: Optional[str] = None,
523
- permission_classes: Optional[list[type[BasePermission]]] = None,
524
- deprecation_reason: Optional[str] = None,
501
+ description: str | None = None,
502
+ permission_classes: list[type[BasePermission]] | None = None,
503
+ deprecation_reason: str | None = None,
525
504
  default: Any = dataclasses.MISSING,
526
- default_factory: Union[Callable[..., object], object] = dataclasses.MISSING,
527
- metadata: Optional[Mapping[Any, Any]] = None,
528
- directives: Optional[Sequence[object]] = (),
529
- extensions: Optional[list[FieldExtension]] = None,
530
- graphql_type: Optional[Any] = None,
505
+ default_factory: Callable[..., object] | object = dataclasses.MISSING,
506
+ metadata: Mapping[Any, Any] | None = None,
507
+ directives: Sequence[object] | None = (),
508
+ extensions: list[FieldExtension] | None = None,
509
+ graphql_type: Any | None = None,
531
510
  # This init parameter is used by PyRight to determine whether this field
532
511
  # is added in the constructor or not. It is not used to change
533
512
  # any behavior at the moment.
534
- init: Literal[True, False, None] = None,
513
+ init: Literal[True, False] | None = None,
535
514
  ) -> Any:
536
515
  """Annotates a method or property as a GraphQL field.
537
516