strawberry-graphql 0.246.3__py3-none-any.whl → 0.247.0__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.
@@ -26,7 +26,11 @@ from strawberry.http.async_base_view import (
26
26
  AsyncHTTPRequestAdapter,
27
27
  AsyncWebSocketAdapter,
28
28
  )
29
- from strawberry.http.exceptions import HTTPException, NonJsonMessageReceived
29
+ from strawberry.http.exceptions import (
30
+ HTTPException,
31
+ NonJsonMessageReceived,
32
+ NonTextMessageReceived,
33
+ )
30
34
  from strawberry.http.types import FormData, HTTPMethod, QueryParams
31
35
  from strawberry.http.typevars import (
32
36
  Context,
@@ -86,16 +90,19 @@ class AioHTTPWebSocketAdapter(AsyncWebSocketAdapter):
86
90
  self.request = request
87
91
  self.ws = ws
88
92
 
89
- async def iter_json(self) -> AsyncGenerator[Dict[str, object], None]:
93
+ async def iter_json(
94
+ self, *, ignore_parsing_errors: bool = False
95
+ ) -> AsyncGenerator[Dict[str, object], None]:
90
96
  async for ws_message in self.ws:
91
97
  if ws_message.type == http.WSMsgType.TEXT:
92
98
  try:
93
99
  yield ws_message.json()
94
100
  except JSONDecodeError:
95
- raise NonJsonMessageReceived()
101
+ if not ignore_parsing_errors:
102
+ raise NonJsonMessageReceived()
96
103
 
97
104
  elif ws_message.type == http.WSMsgType.BINARY:
98
- raise NonJsonMessageReceived()
105
+ raise NonTextMessageReceived()
99
106
 
100
107
  async def send_json(self, message: Mapping[str, object]) -> None:
101
108
  await self.ws.send_json(message)
@@ -33,7 +33,11 @@ from strawberry.http.async_base_view import (
33
33
  AsyncHTTPRequestAdapter,
34
34
  AsyncWebSocketAdapter,
35
35
  )
36
- from strawberry.http.exceptions import HTTPException, NonJsonMessageReceived
36
+ from strawberry.http.exceptions import (
37
+ HTTPException,
38
+ NonJsonMessageReceived,
39
+ NonTextMessageReceived,
40
+ )
37
41
  from strawberry.http.types import FormData, HTTPMethod, QueryParams
38
42
  from strawberry.http.typevars import (
39
43
  Context,
@@ -85,13 +89,18 @@ class ASGIWebSocketAdapter(AsyncWebSocketAdapter):
85
89
  def __init__(self, request: WebSocket, response: WebSocket) -> None:
86
90
  self.ws = response
87
91
 
88
- async def iter_json(self) -> AsyncGenerator[Dict[str, object], None]:
92
+ async def iter_json(
93
+ self, *, ignore_parsing_errors: bool = False
94
+ ) -> AsyncGenerator[Dict[str, object], None]:
89
95
  try:
90
- try:
91
- while self.ws.application_state != WebSocketState.DISCONNECTED:
96
+ while self.ws.application_state != WebSocketState.DISCONNECTED:
97
+ try:
92
98
  yield await self.ws.receive_json()
93
- except (KeyError, JSONDecodeError):
94
- raise NonJsonMessageReceived()
99
+ except JSONDecodeError: # noqa: PERF203
100
+ if not ignore_parsing_errors:
101
+ raise NonJsonMessageReceived()
102
+ except KeyError:
103
+ raise NonTextMessageReceived()
95
104
  except WebSocketDisconnect: # pragma: no cover
96
105
  pass
97
106
 
@@ -16,7 +16,7 @@ from typing import (
16
16
  from typing_extensions import TypeGuard
17
17
 
18
18
  from strawberry.http.async_base_view import AsyncBaseHTTPView, AsyncWebSocketAdapter
19
- from strawberry.http.exceptions import NonJsonMessageReceived
19
+ from strawberry.http.exceptions import NonJsonMessageReceived, NonTextMessageReceived
20
20
  from strawberry.http.typevars import Context, RootValue
21
21
  from strawberry.subscriptions import GRAPHQL_TRANSPORT_WS_PROTOCOL, GRAPHQL_WS_PROTOCOL
22
22
 
@@ -31,7 +31,9 @@ class ChannelsWebSocketAdapter(AsyncWebSocketAdapter):
31
31
  def __init__(self, request: GraphQLWSConsumer, response: GraphQLWSConsumer) -> None:
32
32
  self.ws_consumer = response
33
33
 
34
- async def iter_json(self) -> AsyncGenerator[Dict[str, object], None]:
34
+ async def iter_json(
35
+ self, *, ignore_parsing_errors: bool = False
36
+ ) -> AsyncGenerator[Dict[str, object], None]:
35
37
  while True:
36
38
  message = await self.ws_consumer.message_queue.get()
37
39
 
@@ -39,12 +41,13 @@ class ChannelsWebSocketAdapter(AsyncWebSocketAdapter):
39
41
  break
40
42
 
41
43
  if message["message"] is None:
42
- raise NonJsonMessageReceived()
44
+ raise NonTextMessageReceived()
43
45
 
44
46
  try:
45
47
  yield json.loads(message["message"])
46
48
  except json.JSONDecodeError:
47
- raise NonJsonMessageReceived()
49
+ if not ignore_parsing_errors:
50
+ raise NonJsonMessageReceived()
48
51
 
49
52
  async def send_json(self, message: Mapping[str, object]) -> None:
50
53
  serialized_message = json.dumps(message)
@@ -81,7 +81,9 @@ class AsyncHTTPRequestAdapter(abc.ABC):
81
81
 
82
82
  class AsyncWebSocketAdapter(abc.ABC):
83
83
  @abc.abstractmethod
84
- def iter_json(self) -> AsyncGenerator[Dict[str, object], None]: ...
84
+ def iter_json(
85
+ self, *, ignore_parsing_errors: bool = False
86
+ ) -> AsyncGenerator[Dict[str, object], None]: ...
85
87
 
86
88
  @abc.abstractmethod
87
89
  async def send_json(self, message: Mapping[str, object]) -> None: ...
@@ -4,6 +4,10 @@ class HTTPException(Exception):
4
4
  self.reason = reason
5
5
 
6
6
 
7
+ class NonTextMessageReceived(Exception):
8
+ pass
9
+
10
+
7
11
  class NonJsonMessageReceived(Exception):
8
12
  pass
9
13
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import json
5
6
  import warnings
6
7
  from datetime import timedelta
7
8
  from typing import (
@@ -37,7 +38,6 @@ from litestar.background_tasks import BackgroundTasks
37
38
  from litestar.di import Provide
38
39
  from litestar.exceptions import (
39
40
  NotFoundException,
40
- SerializationException,
41
41
  ValidationException,
42
42
  WebSocketDisconnect,
43
43
  )
@@ -49,7 +49,11 @@ from strawberry.http.async_base_view import (
49
49
  AsyncHTTPRequestAdapter,
50
50
  AsyncWebSocketAdapter,
51
51
  )
52
- from strawberry.http.exceptions import HTTPException, NonJsonMessageReceived
52
+ from strawberry.http.exceptions import (
53
+ HTTPException,
54
+ NonJsonMessageReceived,
55
+ NonTextMessageReceived,
56
+ )
53
57
  from strawberry.http.types import FormData, HTTPMethod, QueryParams
54
58
  from strawberry.http.typevars import Context, RootValue
55
59
  from strawberry.subscriptions import GRAPHQL_TRANSPORT_WS_PROTOCOL, GRAPHQL_WS_PROTOCOL
@@ -192,13 +196,22 @@ class LitestarWebSocketAdapter(AsyncWebSocketAdapter):
192
196
  def __init__(self, request: WebSocket, response: WebSocket) -> None:
193
197
  self.ws = response
194
198
 
195
- async def iter_json(self) -> AsyncGenerator[Dict[str, object], None]:
199
+ async def iter_json(
200
+ self, *, ignore_parsing_errors: bool = False
201
+ ) -> AsyncGenerator[Dict[str, object], None]:
196
202
  try:
197
- try:
198
- while self.ws.connection_state != "disconnect":
199
- yield await self.ws.receive_json()
200
- except (SerializationException, ValueError):
201
- raise NonJsonMessageReceived()
203
+ while self.ws.connection_state != "disconnect":
204
+ text = await self.ws.receive_text()
205
+
206
+ # Litestar internally defaults to an empty string for non-text messages
207
+ if text == "":
208
+ raise NonTextMessageReceived()
209
+
210
+ try:
211
+ yield json.loads(text)
212
+ except json.JSONDecodeError:
213
+ if not ignore_parsing_errors:
214
+ raise NonJsonMessageReceived()
202
215
  except WebSocketDisconnect:
203
216
  pass
204
217
 
@@ -15,7 +15,7 @@ from typing import (
15
15
 
16
16
  from graphql import GraphQLError, GraphQLSyntaxError, parse
17
17
 
18
- from strawberry.http.exceptions import NonJsonMessageReceived
18
+ from strawberry.http.exceptions import NonJsonMessageReceived, NonTextMessageReceived
19
19
  from strawberry.subscriptions.protocols.graphql_transport_ws.types import (
20
20
  CompleteMessage,
21
21
  ConnectionAckMessage,
@@ -78,8 +78,10 @@ class BaseGraphQLTransportWSHandler:
78
78
  try:
79
79
  async for message in self.websocket.iter_json():
80
80
  await self.handle_message(message)
81
- except NonJsonMessageReceived:
81
+ except NonTextMessageReceived:
82
82
  await self.handle_invalid_message("WebSocket message type must be text")
83
+ except NonJsonMessageReceived:
84
+ await self.handle_invalid_message("WebSocket message must be valid JSON")
83
85
  finally:
84
86
  await self.shutdown()
85
87
 
@@ -11,7 +11,7 @@ from typing import (
11
11
  cast,
12
12
  )
13
13
 
14
- from strawberry.http.exceptions import NonJsonMessageReceived
14
+ from strawberry.http.exceptions import NonTextMessageReceived
15
15
  from strawberry.subscriptions.protocols.graphql_ws import (
16
16
  GQL_COMPLETE,
17
17
  GQL_CONNECTION_ACK,
@@ -65,9 +65,9 @@ class BaseGraphQLWSHandler:
65
65
 
66
66
  async def handle(self) -> None:
67
67
  try:
68
- async for message in self.websocket.iter_json():
68
+ async for message in self.websocket.iter_json(ignore_parsing_errors=True):
69
69
  await self.handle_message(cast(OperationMessage, message))
70
- except NonJsonMessageReceived:
70
+ except NonTextMessageReceived:
71
71
  await self.websocket.close(
72
72
  code=1002, reason="WebSocket message type must be text"
73
73
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: strawberry-graphql
3
- Version: 0.246.3
3
+ Version: 0.247.0
4
4
  Summary: A library for creating GraphQL APIs
5
5
  Home-page: https://strawberry.rocks/
6
6
  License: MIT
@@ -3,9 +3,9 @@ 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=xPwOo1V0XbC86LWHiSRTLcGNOa796flz49wzWmdkvSs,1775
6
- strawberry/aiohttp/views.py,sha256=wbJkcQ1u98tuHa3_mq8OCGzSm57Nnw4DnS5qkILHlEo,7487
6
+ strawberry/aiohttp/views.py,sha256=Y7seaVmuz2jLQfgcYOhQLQW5oDEIVrHqZoiqe49VVnI,7636
7
7
  strawberry/annotation.py,sha256=u5rkFs6CDUaiJZMK7jp_VDUWdZZ3HXQEbR2ocruDpxA,13065
8
- strawberry/asgi/__init__.py,sha256=aAZxRFESgbDNXzByT_O9oocolwCj4wB491w6jYKKsiU,7627
8
+ strawberry/asgi/__init__.py,sha256=2_dRxUUaXp-tMWB9kebutLFK9BH-hSMP6vwmveZHJHQ,7857
9
9
  strawberry/asgi/test/__init__.py,sha256=4xxdUZtIISSOwjrcnmox7AvT4WWjowCm5bUuPdQneMg,71
10
10
  strawberry/asgi/test/client.py,sha256=VolupxMna9ktF1lYgV_dUQAIN53DNzVyWTeWTbwsxqE,1448
11
11
  strawberry/chalice/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -14,7 +14,7 @@ strawberry/channels/__init__.py,sha256=-9ENTIu1AILbqffJ663qH6AwpZgLrJx_kaokS7RrC
14
14
  strawberry/channels/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  strawberry/channels/handlers/base.py,sha256=KV4KA0eF5NRtikV9m4ssoPI5pmCZvDuRkfoTxwh42qI,7853
16
16
  strawberry/channels/handlers/http_handler.py,sha256=fnQcPwdUz2CboVlnI3s1urQ_ZnZyNZvRx7SM_xPLLEA,11577
17
- strawberry/channels/handlers/ws_handler.py,sha256=mkfYKtGQO7So4BVBcUHQqG0vUVWIx55vHbJq-D5kz5Y,5924
17
+ strawberry/channels/handlers/ws_handler.py,sha256=k9xax8S1g0tfEFSe76UOHkheHqIrnYjEioYlLm4UPLo,6052
18
18
  strawberry/channels/router.py,sha256=DKIbl4zuRBhfvViUVpyu0Rf_WRT41E6uZC-Yic9Ltvo,2024
19
19
  strawberry/channels/testing.py,sha256=GZqYu_rhrT1gLHmdI219L1fctVDmrv7AMHs0bwhXitc,6166
20
20
  strawberry/cli/__init__.py,sha256=byS5VrEiTJatAH6YS4V1Kd4SOwMRAQO2M1oJdIddivg,585
@@ -132,9 +132,9 @@ strawberry/file_uploads/utils.py,sha256=2zsXg3QsKgGLD7of2dW-vgQn_Naf7I3Men9PhEAF
132
132
  strawberry/flask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
133
133
  strawberry/flask/views.py,sha256=3gd1Xgxg3IT72dz2nrMBK094dMNxTUHciu3oofGOAG4,6235
134
134
  strawberry/http/__init__.py,sha256=GSvHUDXl1cHfLnb37PXOAnxfoXhvz0f467P1O8uDatM,1620
135
- strawberry/http/async_base_view.py,sha256=ZWxxLNCISinp9nc7878_0FjRt8y-giQbtJgSF-Q4ZF0,15688
135
+ strawberry/http/async_base_view.py,sha256=n4Kg9sG9awN7EWa0JIQUmMtnyfI6aqRmg3n2IkoQ_F4,15742
136
136
  strawberry/http/base.py,sha256=DFGBb6UhHR1EOmZkLn5V-2IKXzjYasg6yv06PQnm9Ds,2336
137
- strawberry/http/exceptions.py,sha256=-mRC6RALAj3XCaKeYvHNDiIRAMbE_GbVd7TEAgqRocA,245
137
+ strawberry/http/exceptions.py,sha256=6AF0F-Y_CGReeLtZefN4ApJw0cYWfLctvHGWL6NuNTM,297
138
138
  strawberry/http/ides.py,sha256=njYI2b5R0PnY27ll1ePdIvgPQU3m6Aod_JTBrcZYs0U,638
139
139
  strawberry/http/parse_content_type.py,sha256=sgtcOO_ZOFg7WWWibYyLc4SU58K-SErcW56kQczQmKU,412
140
140
  strawberry/http/sync_base_view.py,sha256=qA9o-Ic4ZcTXiKF02lBsrN7ET6VeXGYWf9m9mjhlfWU,7199
@@ -142,7 +142,7 @@ strawberry/http/temporal_response.py,sha256=QrGYSg7Apu7Mh-X_uPKDZby-UicXw2J_ywxa
142
142
  strawberry/http/types.py,sha256=cAuaiUuvaMI_XhZ2Ey6Ej23WyQKqMGFxzzpVHDjVazY,371
143
143
  strawberry/http/typevars.py,sha256=8hK5PfNPZXb2EhZmqlobYyfwJJcO2Wb96T91MlLEVJs,450
144
144
  strawberry/litestar/__init__.py,sha256=zsXzg-mglCGUVO9iNXLm-yadoDSCK7k-zuyRqyvAh1w,237
145
- strawberry/litestar/controller.py,sha256=oKjio86UsFjvdwxx80YqX_-WWnw51Sd7saMulQ0ihIQ,13519
145
+ strawberry/litestar/controller.py,sha256=vGLfjnTb6AljROkAy4nUdzr08BeDF5dJFrjDO26NBJM,13856
146
146
  strawberry/parent.py,sha256=sXURm0lauSpjUADsmfNGY-Zl7kHs0A67BFcWuWKzRxw,771
147
147
  strawberry/permission.py,sha256=HusiB46yZANdpZM3AdzFVZB6JkCu7dcvoZ3QP2E01jM,7575
148
148
  strawberry/printer/__init__.py,sha256=DmepjmgtkdF5RxK_7yC6qUyRWn56U-9qeZMbkztYB9w,62
@@ -187,10 +187,10 @@ strawberry/static/pathfinder.html,sha256=0DPx9AmJ2C_sJstFXnWOz9k5tVQHeHaK7qdVY4l
187
187
  strawberry/subscriptions/__init__.py,sha256=1VGmiCzFepqRFyCikagkUoHHdoTG3XYlFu9GafoQMws,170
188
188
  strawberry/subscriptions/protocols/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
189
189
  strawberry/subscriptions/protocols/graphql_transport_ws/__init__.py,sha256=wN6dkMu6WiaIZTE19PGoN9xXpIN_RdDE_q7F7ZgjCxk,138
190
- strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py,sha256=oh1XUlhl3lZx0bAU1Ta7cC9f9nuDbJGFnxRlm1z6ud8,14388
190
+ strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py,sha256=WE45AJp3D7LO4tKnFfapQnAK5D1a7Liv3aY5Ga7fvvU,14537
191
191
  strawberry/subscriptions/protocols/graphql_transport_ws/types.py,sha256=udYxzGtwjETYvY5f23org0t-aY4cimTjEGFYUR3idaY,2596
192
192
  strawberry/subscriptions/protocols/graphql_ws/__init__.py,sha256=ijn1A1O0Fzv5p9n-jw3T5H7M3oxbN4gbxRaepN7HyJk,553
193
- strawberry/subscriptions/protocols/graphql_ws/handlers.py,sha256=QxCribyj-EP9SFblbUd4GxK4dMdJe-P8TsjYPwaXf-8,7556
193
+ strawberry/subscriptions/protocols/graphql_ws/handlers.py,sha256=1Cy3GGQfiAhKJNAvGESR1WElzh4g9YsKYnhFuQoxt-0,7582
194
194
  strawberry/subscriptions/protocols/graphql_ws/types.py,sha256=CKm4Hy95p6H9u_-QyWdxipwzNeeDIWtilP3RRp8vjPw,1050
195
195
  strawberry/test/__init__.py,sha256=U3B5Ng7C_H8GpCpfvgZZcfADMw6cor5hm78gS3nDdMI,115
196
196
  strawberry/test/client.py,sha256=Va7J1tIjZ6PxbOqPl57jSp5lNLOZSueHPmrUuUx5sRY,6462
@@ -230,8 +230,8 @@ strawberry/utils/logging.py,sha256=U1cseHGquN09YFhFmRkiphfASKCyK0HUZREImPgVb0c,7
230
230
  strawberry/utils/operation.py,sha256=SSXxN-vMqdHO6W2OZtip-1z7y4_A-eTVFdhDvhKeLCk,1193
231
231
  strawberry/utils/str_converters.py,sha256=KGd7QH90RevaJjH6SQEkiVVsb8KuhJr_wv5AsI7UzQk,897
232
232
  strawberry/utils/typing.py,sha256=3xws5kxSQGsp8BnYyUwClvxXNzZakMAuOPoq1rjHRuk,14252
233
- strawberry_graphql-0.246.3.dist-info/LICENSE,sha256=m-XnIVUKqlG_AWnfi9NReh9JfKhYOB-gJfKE45WM1W8,1072
234
- strawberry_graphql-0.246.3.dist-info/METADATA,sha256=Q7vLEXz9pa7Nxmw2LwvWhS6Zw6K6BGlkOtyj979K154,7758
235
- strawberry_graphql-0.246.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
236
- strawberry_graphql-0.246.3.dist-info/entry_points.txt,sha256=Nk7-aT3_uEwCgyqtHESV9H6Mc31cK-VAvhnQNTzTb4k,49
237
- strawberry_graphql-0.246.3.dist-info/RECORD,,
233
+ strawberry_graphql-0.247.0.dist-info/LICENSE,sha256=m-XnIVUKqlG_AWnfi9NReh9JfKhYOB-gJfKE45WM1W8,1072
234
+ strawberry_graphql-0.247.0.dist-info/METADATA,sha256=BIXpXvq7MkMvSToInnl-p1uTVQR_SR1YwogjRYOTSFs,7758
235
+ strawberry_graphql-0.247.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
236
+ strawberry_graphql-0.247.0.dist-info/entry_points.txt,sha256=Nk7-aT3_uEwCgyqtHESV9H6Mc31cK-VAvhnQNTzTb4k,49
237
+ strawberry_graphql-0.247.0.dist-info/RECORD,,