9
9
import json
10
10
from collections import namedtuple
11
11
from collections .abc import MutableMapping
12
- from typing import Any , Callable , Dict , List , Optional , Type , Union
12
+ from typing import Any , Callable , Collection , Dict , List , Optional , Type , Union
13
13
14
- from graphql import ExecutionResult , GraphQLError , GraphQLSchema , OperationType
15
- from graphql import format_error as format_error_default
16
- from graphql import get_operation_ast , parse
17
- from graphql .graphql import graphql , graphql_sync
14
+ from graphql . error import GraphQLError
15
+ from graphql . error import format_error as format_error_default
16
+ from graphql . execution import ExecutionResult , execute
17
+ from graphql .language import OperationType , parse
18
18
from graphql .pyutils import AwaitableOrValue
19
+ from graphql .type import GraphQLSchema , validate_schema
20
+ from graphql .utilities import get_operation_ast
21
+ from graphql .validation import ASTValidationRule , validate
19
22
20
23
from .error import HttpQueryError
21
24
from .version import version , version_info
@@ -223,36 +226,48 @@ def load_json_variables(variables: Optional[Union[str, Dict]]) -> Optional[Dict]
223
226
return variables # type: ignore
224
227
225
228
229
+ def assume_not_awaitable (_value : Any ) -> bool :
230
+ """Replacement for isawaitable if everything is assumed to be synchronous."""
231
+ return False
232
+
233
+
226
234
def get_response (
227
235
schema : GraphQLSchema ,
228
236
params : GraphQLParams ,
229
237
catch_exc : Type [BaseException ],
230
238
allow_only_query : bool = False ,
231
239
run_sync : bool = True ,
240
+ validation_rules : Optional [Collection [Type [ASTValidationRule ]]] = None ,
241
+ max_errors : Optional [int ] = None ,
232
242
** kwargs ,
233
243
) -> Optional [AwaitableOrValue [ExecutionResult ]]:
234
244
"""Get an individual execution result as response, with option to catch errors.
235
245
236
- This does the same as graphql_impl() except that you can either
237
- throw an error on the ExecutionResult if allow_only_query is set to True
238
- or catch errors that belong to an exception class that you need to pass
239
- as a parameter.
246
+ This will validate the schema (if the schema is used for the first time),
247
+ parse the query, check if this is a query if allow_only_query is set to True,
248
+ validate the query (optionally with additional validation rules and limiting
249
+ the number of errors), execute the request (asynchronously if run_sync is not
250
+ set to True), and return the ExecutionResult. You can also catch all errors that
251
+ belong to an exception class specified by catch_exc.
240
252
"""
241
-
242
253
# noinspection PyBroadException
243
254
try :
244
255
if not params .query :
245
256
raise HttpQueryError (400 , "Must provide query string." )
246
257
258
+ schema_validation_errors = validate_schema (schema )
259
+ if schema_validation_errors :
260
+ return ExecutionResult (data = None , errors = schema_validation_errors )
261
+
262
+ try :
263
+ document = parse (params .query )
264
+ except GraphQLError as e :
265
+ return ExecutionResult (data = None , errors = [e ])
266
+ except Exception as e :
267
+ e = GraphQLError (str (e ), original_error = e )
268
+ return ExecutionResult (data = None , errors = [e ])
269
+
247
270
if allow_only_query :
248
- # Parse document to check that only query operations are used
249
- try :
250
- document = parse (params .query )
251
- except GraphQLError as e :
252
- return ExecutionResult (data = None , errors = [e ])
253
- except Exception as e :
254
- e = GraphQLError (str (e ), original_error = e )
255
- return ExecutionResult (data = None , errors = [e ])
256
271
operation_ast = get_operation_ast (document , params .operation_name )
257
272
if operation_ast :
258
273
operation = operation_ast .operation .value
@@ -264,22 +279,21 @@ def get_response(
264
279
headers = {"Allow" : "POST" },
265
280
)
266
281
267
- if run_sync :
268
- execution_result = graphql_sync (
269
- schema = schema ,
270
- source = params .query ,
271
- variable_values = params .variables ,
272
- operation_name = params .operation_name ,
273
- ** kwargs ,
274
- )
275
- else :
276
- execution_result = graphql ( # type: ignore
277
- schema = schema ,
278
- source = params .query ,
279
- variable_values = params .variables ,
280
- operation_name = params .operation_name ,
281
- ** kwargs ,
282
- )
282
+ validation_errors = validate (
283
+ schema , document , rules = validation_rules , max_errors = max_errors
284
+ )
285
+ if validation_errors :
286
+ return ExecutionResult (data = None , errors = validation_errors )
287
+
288
+ execution_result = execute (
289
+ schema ,
290
+ document ,
291
+ variable_values = params .variables ,
292
+ operation_name = params .operation_name ,
293
+ is_awaitable = assume_not_awaitable if run_sync else None ,
294
+ ** kwargs ,
295
+ )
296
+
283
297
except catch_exc :
284
298
return None
285
299
0 commit comments