strawberry-graphql 0.266.0__py3-none-any.whl → 0.266.1__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.
strawberry/__init__.py CHANGED
@@ -18,6 +18,7 @@ from .types.enum import enum, enum_value
18
18
  from .types.field import field
19
19
  from .types.info import Info
20
20
  from .types.lazy_type import LazyType, lazy
21
+ from .types.maybe import Maybe, Some
21
22
  from .types.mutation import mutation, subscription
22
23
  from .types.object_type import asdict, input, interface, type # noqa: A004
23
24
  from .types.private import Private
@@ -31,9 +32,11 @@ __all__ = [
31
32
  "BasePermission",
32
33
  "Info",
33
34
  "LazyType",
35
+ "Maybe",
34
36
  "Parent",
35
37
  "Private",
36
38
  "Schema",
39
+ "Some",
37
40
  "argument",
38
41
  "asdict",
39
42
  "auto",
strawberry/annotation.py CHANGED
@@ -19,6 +19,7 @@ from typing_extensions import Self, get_args, get_origin
19
19
 
20
20
  from strawberry.types.base import (
21
21
  StrawberryList,
22
+ StrawberryMaybe,
22
23
  StrawberryObjectDefinition,
23
24
  StrawberryOptional,
24
25
  StrawberryTypeVar,
@@ -28,6 +29,7 @@ from strawberry.types.base import (
28
29
  from strawberry.types.enum import EnumDefinition
29
30
  from strawberry.types.enum import enum as strawberry_enum
30
31
  from strawberry.types.lazy_type import LazyType
32
+ from strawberry.types.maybe import _annotation_is_maybe
31
33
  from strawberry.types.private import is_private
32
34
  from strawberry.types.scalar import ScalarDefinition
33
35
  from strawberry.types.unset import UNSET
@@ -143,6 +145,10 @@ class StrawberryAnnotation:
143
145
  return evaled_type
144
146
  if self._is_list(evaled_type):
145
147
  return self.create_list(evaled_type)
148
+ if type_of := self._get_maybe_type(evaled_type):
149
+ return StrawberryMaybe(
150
+ of_type=type_of,
151
+ )
146
152
 
147
153
  if self._is_graphql_generic(evaled_type):
148
154
  if any(is_type_var(type_) for type_ in get_args(evaled_type)):
@@ -313,6 +319,10 @@ class StrawberryAnnotation:
313
319
  or is_list
314
320
  )
315
321
 
322
+ @classmethod
323
+ def _get_maybe_type(cls, annotation: Any) -> type | None:
324
+ return get_args(annotation)[0] if _annotation_is_maybe(annotation) else None
325
+
316
326
  @classmethod
317
327
  def _is_strawberry_type(cls, evaled_type: Any) -> bool:
318
328
  # Prevent import cycles
@@ -52,6 +52,7 @@ from strawberry.schema.types.scalar import _make_scalar_type
52
52
  from strawberry.types.arguments import StrawberryArgument, convert_arguments
53
53
  from strawberry.types.base import (
54
54
  StrawberryList,
55
+ StrawberryMaybe,
55
56
  StrawberryObjectDefinition,
56
57
  StrawberryOptional,
57
58
  StrawberryType,
@@ -254,7 +255,10 @@ class GraphQLCoreConverter:
254
255
  argument_type = cast(
255
256
  "GraphQLInputType", self.from_maybe_optional(argument.type)
256
257
  )
257
- default_value = Undefined if argument.default is UNSET else argument.default
258
+ if argument.is_maybe:
259
+ default_value: Any = Undefined
260
+ else:
261
+ default_value = Undefined if argument.default is UNSET else argument.default
258
262
 
259
263
  return GraphQLArgument(
260
264
  type_=argument_type,
@@ -419,8 +423,9 @@ class GraphQLCoreConverter:
419
423
  ),
420
424
  )
421
425
  default_value: object
422
-
423
- if field.default_value is UNSET or field.default_value is dataclasses.MISSING:
426
+ if isinstance(field.type, StrawberryMaybe):
427
+ default_value = Undefined
428
+ elif field.default_value is UNSET or field.default_value is dataclasses.MISSING:
424
429
  default_value = Undefined
425
430
  else:
426
431
  default_value = field.default_value
@@ -17,13 +17,17 @@ from strawberry.exceptions import MultipleStrawberryArgumentsError, UnsupportedT
17
17
  from strawberry.scalars import is_scalar
18
18
  from strawberry.types.base import (
19
19
  StrawberryList,
20
+ StrawberryMaybe,
20
21
  StrawberryOptional,
21
22
  has_object_definition,
22
23
  )
23
24
  from strawberry.types.enum import EnumDefinition
24
25
  from strawberry.types.lazy_type import LazyType, StrawberryLazyReference
26
+ from strawberry.types.maybe import Some
25
27
  from strawberry.types.unset import UNSET as _deprecated_UNSET # noqa: N811
26
- from strawberry.types.unset import _deprecated_is_unset # noqa: F401
28
+ from strawberry.types.unset import (
29
+ _deprecated_is_unset, # noqa: F401
30
+ )
27
31
 
28
32
  if TYPE_CHECKING:
29
33
  from collections.abc import Iterable, Mapping
@@ -135,6 +139,10 @@ class StrawberryArgument:
135
139
 
136
140
  return is_graphql_generic(self.type)
137
141
 
142
+ @property
143
+ def is_maybe(self) -> bool:
144
+ return isinstance(self.type, StrawberryMaybe)
145
+
138
146
 
139
147
  def convert_argument(
140
148
  value: object,
@@ -143,6 +151,10 @@ def convert_argument(
143
151
  config: StrawberryConfig,
144
152
  ) -> object:
145
153
  # TODO: move this somewhere else and make it first class
154
+ if isinstance(type_, StrawberryOptional):
155
+ res = convert_argument(value, type_.of_type, scalar_registry, config)
156
+
157
+ return Some(res) if isinstance(type_, StrawberryMaybe) else res
146
158
 
147
159
  if value is None:
148
160
  return None
@@ -150,9 +162,6 @@ def convert_argument(
150
162
  if value is _deprecated_UNSET:
151
163
  return _deprecated_UNSET
152
164
 
153
- if isinstance(type_, StrawberryOptional):
154
- return convert_argument(value, type_.of_type, scalar_registry, config)
155
-
156
165
  if isinstance(type_, StrawberryList):
157
166
  value_list = cast("Iterable", value)
158
167
  return [
strawberry/types/base.py CHANGED
@@ -152,7 +152,16 @@ class StrawberryContainer(StrawberryType):
152
152
  class StrawberryList(StrawberryContainer): ...
153
153
 
154
154
 
155
- class StrawberryOptional(StrawberryContainer): ...
155
+ class StrawberryOptional(StrawberryContainer):
156
+ def __init__(
157
+ self,
158
+ of_type: Union[StrawberryType, type[WithStrawberryObjectDefinition], type],
159
+ ) -> None:
160
+ super().__init__(of_type)
161
+
162
+
163
+ class StrawberryMaybe(StrawberryOptional):
164
+ pass
156
165
 
157
166
 
158
167
  class StrawberryTypeVar(StrawberryType):
@@ -0,0 +1,47 @@
1
+ import typing
2
+ from typing import TYPE_CHECKING, Any, Generic, TypeVar, Union
3
+ from typing_extensions import TypeAlias
4
+
5
+ T = TypeVar("T")
6
+
7
+
8
+ class Some(Generic[T]):
9
+ """A special value that can be used to represent an unset value in a field or argument.
10
+
11
+ Similar to `undefined` in JavaScript, this value can be used to differentiate between
12
+ a field that was not set and a field that was set to `None` or `null`.
13
+ """
14
+
15
+ __slots__ = ("value",)
16
+
17
+ def __init__(self, value: T) -> None:
18
+ self.value = value
19
+
20
+ def __repr__(self) -> str:
21
+ return f"Some({self.value!r})"
22
+
23
+ def __eq__(self, other: object) -> bool:
24
+ return self.value == other.value if isinstance(other, Some) else False
25
+
26
+ def __hash__(self) -> int:
27
+ return hash(self.value)
28
+
29
+ def __bool__(self) -> bool:
30
+ return True
31
+
32
+
33
+ if TYPE_CHECKING:
34
+ Maybe: TypeAlias = Union[Some[Union[T, None]], None]
35
+ else:
36
+ # we do this trick so we can inspect that at runtime
37
+ class Maybe(Generic[T]): ...
38
+
39
+
40
+ def _annotation_is_maybe(annotation: Any) -> bool:
41
+ return (orig := typing.get_origin(annotation)) and orig is Maybe
42
+
43
+
44
+ __all__ = [
45
+ "Maybe",
46
+ "Some",
47
+ ]
@@ -20,6 +20,7 @@ from strawberry.exceptions import (
20
20
  ObjectIsNotClassError,
21
21
  )
22
22
  from strawberry.types.base import get_object_definition
23
+ from strawberry.types.maybe import _annotation_is_maybe
23
24
  from strawberry.utils.deprecations import DEPRECATION_MESSAGES, DeprecatedDescriptor
24
25
  from strawberry.utils.str_converters import to_camel_case
25
26
 
@@ -122,6 +123,15 @@ def _wrap_dataclass(cls: builtins.type[T]) -> builtins.type[T]:
122
123
  return dclass
123
124
 
124
125
 
126
+ def _inject_default_for_maybe_annotations(
127
+ cls: builtins.type[T], annotations: dict[str, Any]
128
+ ) -> None:
129
+ """Inject `= None` for fields with `Maybe` annotations and no default value."""
130
+ for name, annotation in annotations.copy().items():
131
+ if _annotation_is_maybe(annotation) and not hasattr(cls, name):
132
+ setattr(cls, name, None)
133
+
134
+
125
135
  def _process_type(
126
136
  cls: T,
127
137
  *,
@@ -286,7 +296,8 @@ def type(
286
296
 
287
297
  if field and isinstance(field, StrawberryField) and field.type_annotation:
288
298
  original_type_annotations[field_name] = field.type_annotation.annotation
289
-
299
+ if is_input:
300
+ _inject_default_for_maybe_annotations(cls, annotations)
290
301
  wrapped = _wrap_dataclass(cls)
291
302
 
292
303
  return _process_type( # type: ignore
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: strawberry-graphql
3
- Version: 0.266.0
3
+ Version: 0.266.1
4
4
  Summary: A library for creating GraphQL APIs
5
5
  License: MIT
6
6
  Keywords: graphql,api,rest,starlette,async
@@ -1,10 +1,10 @@
1
- strawberry/__init__.py,sha256=VcqNwegcJS_YhCOrZyveD_wBcd-hh8KKrXcIlTc7knE,1429
1
+ strawberry/__init__.py,sha256=-K---AYIgHvBVYF_9oovgEPNBbymXH673bntlV9sOeU,1491
2
2
  strawberry/__main__.py,sha256=3U77Eu21mJ-LY27RG-JEnpbh6Z63wGOom4i-EoLtUcY,59
3
3
  strawberry/aiohttp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  strawberry/aiohttp/test/__init__.py,sha256=4xxdUZtIISSOwjrcnmox7AvT4WWjowCm5bUuPdQneMg,71
5
5
  strawberry/aiohttp/test/client.py,sha256=8FKZTnvawxYpgEICOri-34O3wHRHLhRpjH_Ktp2EupQ,1801
6
6
  strawberry/aiohttp/views.py,sha256=AQVBbZTBa127TbQRwoBelTHrVdZnJeGdMYcTfNmoaSc,7887
7
- strawberry/annotation.py,sha256=1gaSo9XivkXwWjpEtsM4h5GLn9XGmPYZbxmLCXyh3dA,13116
7
+ strawberry/annotation.py,sha256=iqSXtJ4pTTLDZRPyil0f-yzpcCm8UYRiwvFWkD5LgpQ,13498
8
8
  strawberry/asgi/__init__.py,sha256=psdKl_52LGkxKKbzZlmwNGZ9jz2FLyLSC7fUhys4FqY,8169
9
9
  strawberry/asgi/test/__init__.py,sha256=4xxdUZtIISSOwjrcnmox7AvT4WWjowCm5bUuPdQneMg,71
10
10
  strawberry/asgi/test/client.py,sha256=kp2O5znHWuAB5VVYO8p4XPSTEDDXBSjNz5WHqW0r6GM,1473
@@ -168,7 +168,7 @@ strawberry/schema/config.py,sha256=6BpCbNNCuekGgiKEPt2mliMqLH_wIjJmSW0tLbnJwk4,9
168
168
  strawberry/schema/exceptions.py,sha256=rqVNb_oYrKM0dHPgvAemqCG6Um282LPPu4zwQ5cZqs4,584
169
169
  strawberry/schema/name_converter.py,sha256=xFOXEgqldFkxXRkIQvsJN1dPkWbEUaIrTYNOMYSEVwQ,6945
170
170
  strawberry/schema/schema.py,sha256=qthZttzb9a0GEcwh7trqBKHmuPXOgQlnceqiCRPj4_s,34566
171
- strawberry/schema/schema_converter.py,sha256=OkJaYrWKGqcxdhoTeuf0aGqiTnWtDuZwYddY5uBlf8Q,37521
171
+ strawberry/schema/schema_converter.py,sha256=ZNgpE-cTt0Hqw21yoT-3Fu2xk8SVC3uDq85V9JeKI7Q,37724
172
172
  strawberry/schema/types/__init__.py,sha256=oHO3COWhL3L1KLYCJNY1XFf5xt2GGtHiMC-UaYbFfnA,68
173
173
  strawberry/schema/types/base_scalars.py,sha256=JRUq0WjEkR9dFewstZnqnZKp0uOEipo4UXNF5dzRf4M,1971
174
174
  strawberry/schema/types/concrete_type.py,sha256=axIyFZgdwNv-XYkiqX67464wuFX6Vp0jYATwnBZSUvM,750
@@ -195,9 +195,9 @@ strawberry/tools/__init__.py,sha256=pdGpZx8wpq03VfUZJyF9JtYxZhGqzzxCiipsalWxJX4,
195
195
  strawberry/tools/create_type.py,sha256=--DgfZOmXJBKGcVxehNISyvpw1HzwFvRtUUPc0634MA,2056
196
196
  strawberry/tools/merge_types.py,sha256=hUMRRNM28FyPp70jRA3d4svv9WoEBjaNpihBt3DaY0I,1023
197
197
  strawberry/types/__init__.py,sha256=baWEdDkkmCcITOhkg2hNUOenrNV1OYdxGE5qgvIRwwU,351
198
- strawberry/types/arguments.py,sha256=Ny4meiKYtcXpAV0rFKWJXOJK5iQB-zs-23n0w8S8zVc,9458
198
+ strawberry/types/arguments.py,sha256=y-1yQBZ8ua4lcrlas9PKNZE02seHn95TjGAoTCRc5e8,9700
199
199
  strawberry/types/auto.py,sha256=WZ2cQAI8nREUigBzpzFqIKGjJ_C2VqpAPNe8vPjTciM,3007
200
- strawberry/types/base.py,sha256=rx7J9dGUCUCap0lgb5Yyb_WXnB95FZEY6gQcYasiI9w,14907
200
+ strawberry/types/base.py,sha256=tZSqxtrxXa1Y964HS2uakCbCgLyGO9A4WpODiegWzF8,15122
201
201
  strawberry/types/cast.py,sha256=fx86MkLW77GIximBAwUk5vZxSGwDqUA6XicXvz8EXwQ,916
202
202
  strawberry/types/enum.py,sha256=IcCz0FLswJtDC_bU8aG1cjreawcqHywAzzVRBZUSAqs,6229
203
203
  strawberry/types/execution.py,sha256=Ylc0lH0nyHyQW509mVqBh2sIN5qpf4cJtt8QhVmWGgI,3749
@@ -207,9 +207,10 @@ strawberry/types/fields/resolver.py,sha256=iYYVUVpm-JM3AFQHuQFeOooftiQWFw3kg64pq
207
207
  strawberry/types/graphql.py,sha256=gXKzawwKiow7hvoJhq5ApNJOMUCnKmvTiHaKY5CK1Lw,867
208
208
  strawberry/types/info.py,sha256=bPP7XTQQScmskJcmVv36iqLAWpdGmF2nhYjI1pJ-csI,4709
209
209
  strawberry/types/lazy_type.py,sha256=dlP9VcMjZc9sdgriiQGzOZa0TToB6Ee7zpIP8h7TLC0,5079
210
+ strawberry/types/maybe.py,sha256=Zdv4pAJwgUmaFNU8WKlwjk50qwgYEzT90WteURZBzAo,1174
210
211
  strawberry/types/mutation.py,sha256=cg-_O2WWnZ-GSwOIv0toSdxlGeY2lhBBxZ24AifJuSM,11978
211
212
  strawberry/types/nodes.py,sha256=RwZB43OT9BS3Cqjgq4AazqOfyq_y0GD2ysC86EDBv5U,5134
212
- strawberry/types/object_type.py,sha256=CW-detiYjGmk4kHJP-vUK9sBkBuDic4nswDub4zUyvc,15075
213
+ strawberry/types/object_type.py,sha256=SZOzxaS318079G-pr-1PM5iMoTddxdw8KD4cI67IhzI,15579
213
214
  strawberry/types/private.py,sha256=DhJs50XVGtOXlxWZFkRpMxQ5_6oki0-x_WQsV1bGUxk,518
214
215
  strawberry/types/scalar.py,sha256=CM24Ixg4DKxxI1C6hTNGYVitohJibs8BpGtntRZvMXw,6284
215
216
  strawberry/types/type_resolver.py,sha256=fH2ZOK4dAGgu8AMPi-JAXe_kEAbvvw2MCYXqbpx-kTc,6529
@@ -228,8 +229,8 @@ strawberry/utils/logging.py,sha256=U1cseHGquN09YFhFmRkiphfASKCyK0HUZREImPgVb0c,7
228
229
  strawberry/utils/operation.py,sha256=s7ajvLg_q6v2mg47kEMQPjO_J-XluMKTCwo4d47mGvE,1195
229
230
  strawberry/utils/str_converters.py,sha256=-eH1Cl16IO_wrBlsGM-km4IY0IKsjhjnSNGRGOwQjVM,897
230
231
  strawberry/utils/typing.py,sha256=Xmnhwvnw8RIQVIc5D5iI4_9qM4Thpk7tWx8xf-RW_So,13383
231
- strawberry_graphql-0.266.0.dist-info/LICENSE,sha256=m-XnIVUKqlG_AWnfi9NReh9JfKhYOB-gJfKE45WM1W8,1072
232
- strawberry_graphql-0.266.0.dist-info/METADATA,sha256=NHtUpiQOm0Urof6R0H9vRIlBJzRpQyVDq3BEAgBHoGs,7679
233
- strawberry_graphql-0.266.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
234
- strawberry_graphql-0.266.0.dist-info/entry_points.txt,sha256=Nk7-aT3_uEwCgyqtHESV9H6Mc31cK-VAvhnQNTzTb4k,49
235
- strawberry_graphql-0.266.0.dist-info/RECORD,,
232
+ strawberry_graphql-0.266.1.dist-info/LICENSE,sha256=m-XnIVUKqlG_AWnfi9NReh9JfKhYOB-gJfKE45WM1W8,1072
233
+ strawberry_graphql-0.266.1.dist-info/METADATA,sha256=_RqVVXjFJ7svPPZ9xGPZHsBg5fjlnPAue2seThG3Tjo,7679
234
+ strawberry_graphql-0.266.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
235
+ strawberry_graphql-0.266.1.dist-info/entry_points.txt,sha256=Nk7-aT3_uEwCgyqtHESV9H6Mc31cK-VAvhnQNTzTb4k,49
236
+ strawberry_graphql-0.266.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.2
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any