def test_encode_execution_results_with_batch_and_empty_result(): execution_results = [ ExecutionResult({"result": 1}, None), None, ExecutionResult({"result": 3}, None), ] output = encode_execution_results(execution_results, is_batch=True) assert isinstance(output, ServerResponse) assert isinstance(output.body, str) assert isinstance(output.status_code, int) assert json.loads(output.body) == [ { "data": { "result": 1 } }, None, { "data": { "result": 3 } }, ] assert output.status_code == 200
def execute_graphql_request( self, request: HttpRequest, query: str, variables: dict, operation_name: str): if not query: return ExecutionResult( errors=[ValueError('Must provide a query string.')], invalid=True) try: document = self.backend.document_from_string(self.schema, query) except ValueError as e: return ExecutionResult(errors=[e], invalid=True) extra_options = {} if self.executor: # We only include it optionally since # executor is not a valid argument in all backends extra_options['executor'] = self.executor try: return document.execute( root=self.get_root_value(request), variables=variables, operation_name=operation_name, context=request, middleware=self.middleware, **extra_options) except Exception as e: return ExecutionResult(errors=[e], invalid=True)
def test_encode_execution_results_with_error(): execution_results = [ ExecutionResult( None, [ GraphQLError("Some error", locations=[SourceLocation(1, 2)], path=["somePath"]) ], ), ExecutionResult({"result": 42}, None), ] output = encode_execution_results(execution_results) assert isinstance(output, ServerResponse) assert isinstance(output.body, str) assert isinstance(output.status_code, int) assert json.loads(output.body) == { "data": None, "errors": [{ "message": "Some error", "locations": [{ "line": 1, "column": 2 }], "path": ["somePath"], }], } assert output.status_code == 200
def execute_graphql_request( schema, # type: GraphQLSchema params, # type: GraphQLParams allow_only_query=False, # type: bool backend=None, # type: GraphQLBackend **kwargs # type: Dict ): if not params.query: raise HttpQueryError(400, "Must provide query string.") try: if not backend: backend = get_default_backend() document = backend.document_from_string(schema, params.query) except Exception as e: return ExecutionResult(errors=[e], invalid=True) if allow_only_query: operation_type = document.get_operation_type(params.operation_name) if operation_type and operation_type != "query": raise HttpQueryError( 405, "Can only perform a {} operation from a POST request.".format( operation_type), headers={"Allow": "POST"}, ) try: return document.execute(operation_name=params.operation_name, variables=params.variables, **kwargs) except Exception as e: return ExecutionResult(errors=[e], invalid=True)
def query(self, q): try: source = Source(q, name='GraphQL request') ast = parse(source) validation_errors = validate(self.schema, ast) if validation_errors: return ExecutionResult( errors=validation_errors, invalid=True, ) except Exception as e: return ExecutionResult(errors=[e], invalid=True) try: return execute(self.__schema, ast, root_value=None, variable_values={}, operation_name=None, context_value={ 'query': q, 'introspection': 'introspection' in q.lower() }, middleware=self.__middleware, executor=self.__executor) except Exception as e: return ExecutionResult(errors=[e], invalid=True)
def execute_graphql_request(self, request: HttpRequest, data: dict): with opentracing.global_tracer().start_active_span( "graphql_query") as scope: span = scope.span span.set_tag(opentracing.tags.COMPONENT, "graphql") query, variables, operation_name = self.get_graphql_params( request, data) document, error = self.parse_query(query) if error: return error if document is not None: raw_query_string = document.document_string span.set_tag("graphql.query", raw_query_string) span.set_tag("graphql.query_fingerprint", query_fingerprint(document)) try: query_contains_schema = self.check_if_query_contains_only_schema( document) except GraphQLError as e: return ExecutionResult(errors=[e], invalid=True) extra_options: Dict[str, Optional[Any]] = {} if self.executor: # We only include it optionally since # executor is not a valid argument in all backends extra_options["executor"] = self.executor try: with connection.execute_wrapper(tracing_wrapper): response = None should_use_cache_for_scheme = query_contains_schema & ( not settings.DEBUG) if should_use_cache_for_scheme: key = generate_cache_key(raw_query_string) response = cache.get(key) if not response: response = document.execute( # type: ignore root=self.get_root_value(), variables=variables, operation_name=operation_name, context=request, middleware=self.middleware, **extra_options, ) if should_use_cache_for_scheme: cache.set(key, response) return response except Exception as e: span.set_tag(opentracing.tags.ERROR, True) # In the graphql-core version that we are using, # the Exception is raised for too big integers value. # As it's a validation error we want to raise GraphQLError instead. if str(e).startswith(INT_ERROR_MSG) or isinstance( e, ValueError): e = GraphQLError(str(e)) return ExecutionResult(errors=[e], invalid=True)
def execute_graphql_request(schema, params, allow_only_query=False, backend=None, **kwargs): if not params.query: raise HttpQueryError(400, 'Must provide query string.') try: if not backend: backend = get_default_backend() document = backend.document_from_string(schema, params.query) except Exception as e: return ExecutionResult(errors=[e], invalid=True) if allow_only_query: operation_type = document.get_operation_type(params.operation_name) if operation_type and operation_type != 'query': raise HttpQueryError( 405, 'Can only perform a {} operation from a POST request.'.format( operation_type), headers={ 'Allow': 'POST', }) try: return document.execute(operation_name=params.operation_name, variables=params.variables, **kwargs) except Exception as e: return ExecutionResult(errors=[e], invalid=True)
def execute(document_text, *, graph, variables=None): try: query = parser.document_text_to_query( document_text=document_text, variables=variables, graphql_schema=graphql_schema, ) if query.graph_query is None: result = {} else: result = graph.resolve(query.graph_query) if query.graphql_schema_document is not None: schema_result = _execute_graphql_schema( graphql_schema_document=query.graphql_schema_document, graphql_schema=graphql_schema.graphql_schema, variables=query.variables, ) result = result.copy() result.update(schema_result) return ExecutionResult( data=result, errors=None, ) except (GraphQLError, GraphError) as error: if isinstance(error, GraphError): error = GraphQLError(str(error)) return ExecutionResult( data=None, errors=[error], )
def graphql(schema, request_string='', root_value=None, context_value=None, variable_values=None, operation_name=None, executor=None, return_promise=False, middleware=None): try: source = Source(request_string, 'GraphQL request') ast = parse(source) validation_errors = validate(schema, ast) if validation_errors: return ExecutionResult( errors=validation_errors, invalid=True, ) return execute( schema, ast, root_value, context_value, operation_name=operation_name, variable_values=variable_values or {}, executor=executor, return_promise=return_promise, middleware=middleware, ) except Exception as e: return ExecutionResult( errors=[e], invalid=True, )
def execute(self, root=None, context=None, middleware=None, operation_name=None, variables=None, allowed_operations=None): if self.errors: return ExecutionResult(errors=self.errors, invalid=True) try: if allowed_operations is not None: operation_type = get_operation_from_operation_name( self.document_ast, operation_name) if operation_type and operation_type not in allowed_operations: raise GraphQLError("{} operations are not allowed.".format( operation_type)) return execute(self.schema, self.document_ast, root_value=root, middleware=middleware, context_value=context, variable_values=variables or {}, operation_name=operation_name, **self.execute_params) except Exception as e: return ExecutionResult(errors=[e])
def parse_query( self, query: str ) -> Tuple[Optional[GraphQLDocument], Optional[ExecutionResult]]: """Attempt to parse a query (mandatory) to a gql document object. If no query was given or query is not a string, it returns an error. If the query is invalid, it returns an error as well. Otherwise, it returns the parsed gql document. """ if not query or not isinstance(query, str): return ( None, ExecutionResult( errors=[ValueError("Must provide a query string.")], invalid=True), ) # Attempt to parse the query, if it fails, return the error try: return ( self.backend.document_from_string( # type: ignore self.schema, query), None, ) except (ValueError, GraphQLSyntaxError) as e: return None, ExecutionResult(errors=[e], invalid=True)
def execute_graphql_request( self, request, data, query, variables, operation_name, show_graphiql=False ): if not query: if show_graphiql: return None raise HttpError(HttpResponseBadRequest("Must provide query string.")) try: backend = self.get_backend(request) document = backend.document_from_string(self.schema, query) except Exception as e: return ExecutionResult(errors=[e], invalid=True) if request.method.lower() == "get": operation_type = document.get_operation_type(operation_name) if operation_type and operation_type != "query": if show_graphiql: return None raise HttpError( HttpResponseNotAllowed( ["POST"], "Can only perform a {} operation from a POST request.".format( operation_type ), ) ) try: extra_options = {} if self.executor: # We only include it optionally since # executor is not a valid argument in all backends extra_options["executor"] = self.executor options = { "root_value": self.get_root_value(request), "variable_values": variables, "operation_name": operation_name, "context_value": self.get_context(request), "middleware": self.get_middleware(request), } options.update(extra_options) operation_type = document.get_operation_type(operation_name) if operation_type == "mutation" and ( graphene_settings.ATOMIC_MUTATIONS is True or connection.settings_dict.get("ATOMIC_MUTATIONS", False) is True ): with transaction.atomic(): result = document.execute(**options) if getattr(request, MUTATION_ERRORS_FLAG, False) is True: transaction.set_rollback(True) return result return document.execute(**options) except Exception as e: return ExecutionResult(errors=[e], invalid=True)
def unpacks_as_two_tuple(): res = ExecutionResult(data, errors) res_data, res_errors = res # type: ignore assert res_data == data # type: ignore assert res_errors == errors # type: ignore with raises(ValueError): res = ExecutionResult(data, errors, extensions) _res_data, _res_errors, _res_extensions = res # type: ignore
def test_format_execution_result(): result = format_execution_result(None) assert result == GraphQLResponse(None, 200) data = {"answer": 42} result = format_execution_result(ExecutionResult(data, None)) assert result == GraphQLResponse({"data": data}, 200) errors = [GraphQLError("bad")] result = format_execution_result(ExecutionResult(None, errors)) assert result == GraphQLResponse({"errors": errors}, 400)
def test_encode_execution_results_batch(): data = {"answer": 42} errors = [GraphQLError("bad")] results = [ExecutionResult(data, None), ExecutionResult(None, errors)] result = encode_execution_results(results, is_batch=True) assert result == ( '[{"data":{"answer":42}},{"errors":[{"message":"bad"}]}]', 400, )
def prints_a_representation(): assert repr(ExecutionResult( data, errors)) == ("ExecutionResult(data={'foo': 'Some data'}," " errors=[GraphQLError('Some error')])") assert repr(ExecutionResult( data, errors, extensions)) == ("ExecutionResult(data={'foo': 'Some data'}," " errors=[GraphQLError('Some error')]," " extensions={'bar': 'Some extension'})")
def initializes_properly(): res = ExecutionResult(data, errors) assert res.data is data assert res.errors is errors assert res.extensions is None res = ExecutionResult(data, errors, extensions) assert res.data is data assert res.errors is errors assert res.extensions is extensions
def execute_graphql_request(self, method, query, variables, operation_name, show_graphiql=False): if not query: if show_graphiql: raise Return(None) raise HTTPError(400, 'Must provide query string.') if not self.document: try: backend = self.get_backend() self.document = backend.document_from_string( self.schema, query) except Exception as e: raise Return(ExecutionResult(errors=[e], invalid=True)) try: validation_errors = validate(self.schema, self.document.document_ast) except Exception as e: raise Return(ExecutionResult(errors=[e], invalid=True)) if validation_errors: raise Return( ExecutionResult( errors=validation_errors, invalid=True, )) if method.lower() == 'get': operation_type = self.document.get_operation_type(operation_name) if operation_type and operation_type != "query": if show_graphiql: raise Return(None) raise HTTPError( 405, 'Can only perform a {} operation from a POST request.'. format(operation_type)) try: result = yield self.execute(self.document.document_ast, root=self.get_root(), variables=variables, operation_name=operation_name, context=self.context, middleware=self.get_middleware(), executor=self.executor or TornadoExecutor(), return_promise=True) except Exception as e: raise Return(ExecutionResult(errors=[e], invalid=True)) raise Return(result)
def formats_properly(): res = ExecutionResult(data, errors) assert res.formatted == {"data": data, "errors": errors} res = ExecutionResult(data, errors, extensions) assert res.formatted == { "data": data, "errors": errors, "extensions": extensions, }
def execute_query(self, query: str) -> ExecutionResult: try: ast = get_ast(query) except GraphQLSyntaxError as e: return ExecutionResult(errors=[e], invalid=True) validation_errors = validate(self.schema, ast) if validation_errors: return ExecutionResult(errors=validation_errors, invalid=True) return execute(self.schema, ast)
def execute_query(self, query: str) -> ExecutionResult: source = Source(query) try: document_ast = parse(source=source) except GraphQLSyntaxError as e: return ExecutionResult(errors=[e], invalid=True) validation_errors = validate(self.schema, document_ast) if validation_errors: return ExecutionResult(errors=validation_errors, invalid=True) return execute(self.schema, document_ast)
def execute_graphql_request(self, request, data, query, variables, operation_name, show_graphiql=False): if os.getenv('DEBUG_ESCAPE_GRAPHQL', False) == 'True': return self.escaped_execute_graphql_request( request, data, query, variables, operation_name, show_graphiql) if not query: if show_graphiql: return None raise HttpError( HttpResponseBadRequest('Must provide query string.')) source = Source(query, name='GraphQL request') try: document_ast = parse(source) validation_errors = validate(self.schema, document_ast) if validation_errors: return ExecutionResult( errors=validation_errors, invalid=True, ) except Exception as e: return ExecutionResult(errors=[e], invalid=True) if request.method.lower() == 'get': operation_ast = get_operation_ast(document_ast, operation_name) if operation_ast and operation_ast.operation != 'query': if show_graphiql: return None raise HttpError( HttpResponseNotAllowed( ['POST'], 'Can only perform a {} operation from a POST request.'. format(operation_ast.operation))) try: return self.execute( document_ast, root_value=self.get_root_value(request), variable_values=variables, operation_name=operation_name, context_value=self.get_context(request), middleware=self.get_middleware(request), executor=self.executor, ) except Exception as e: return ExecutionResult(errors=[e], invalid=True)
def compares_to_dict(): res = ExecutionResult(data, errors) assert res == {"data": data, "errors": errors} assert res == {"data": data, "errors": errors, "extensions": None} assert res != {"data": data, "errors": None} assert res != {"data": None, "errors": errors} assert res != {"data": data, "errors": errors, "extensions": extensions} res = ExecutionResult(data, errors, extensions) assert res == {"data": data, "errors": errors} assert res == {"data": data, "errors": errors, "extensions": extensions} assert res != {"data": data, "errors": None} assert res != {"data": None, "errors": errors} assert res != {"data": data, "errors": errors, "extensions": None}
def test_encode_execution_results_without_error(): execution_results = [ ExecutionResult({"result": 1}, None), ExecutionResult({"result": 2}, None), ExecutionResult({"result": 3}, None), ] output = encode_execution_results(execution_results) assert isinstance(output, ServerResponse) assert isinstance(output.body, str) assert isinstance(output.status_code, int) assert json.loads(output.body) == {"data": {"result": 1}} assert output.status_code == 200
def compares_to_tuple(): res = ExecutionResult(data, errors) assert res == (data, errors) assert res == (data, errors, None) assert res != (data, None) assert res != (None, errors) assert res != (data, errors, extensions) res = ExecutionResult(data, errors, extensions) assert res == (data, errors) assert res == (data, errors, extensions) assert res != (data, None) assert res != (None, errors) assert res != (data, errors, None)
def execute_graphql_request(self, method, query, variables, operation_name, show_graphiql=False): if not query: if show_graphiql: raise Return(None) raise HTTPError(400, 'Must provide query string.') source = Source(query, name='GraphQL request') try: document_ast = parse(source) validation_errors = validate(self.schema, document_ast) except Exception as e: raise Return(ExecutionResult(errors=[e], invalid=True)) if validation_errors: raise Return( ExecutionResult( errors=validation_errors, invalid=True, )) if method.lower() == 'get': operation_ast = get_operation_ast(document_ast, operation_name) if operation_ast and operation_ast.operation != 'query': if show_graphiql: raise Return(None) raise HTTPError( 405, 'Can only perform a {} operation from a POST request.'. format(operation_ast.operation)) try: result = yield self.execute(document_ast, root_value=self.root_value, variable_values=variables, operation_name=operation_name, context_value=self.context, middleware=self.middleware, executor=self.executor or TornadoExecutor(), return_promise=True) except Exception as e: raise Return(ExecutionResult(errors=[e], invalid=True)) raise Return(result)
def execute_graphql_request( self, request, data, query, variables, operation_name, show_graphiql=False, ): if not query: if show_graphiql: return None raise HttpError( HttpResponseBadRequest("Must provide query string.")) try: backend = self.get_backend(request) document = backend.document_from_string(self.schema, query) except Exception as e: return ExecutionResult(errors=[e], invalid=True) if request.method.lower() == "get": operation_type = document.get_operation_type(operation_name) if operation_type and operation_type != "query": if show_graphiql: return None raise HttpError( HttpResponseNotAllowed( ["POST"], "Can only perform a {} operation from a POST request.". format(operation_type), )) try: extra_options = {} if self.executor: # We only include it optionally since # executor is not a valid argument in all backends extra_options["executor"] = self.executor return document.execute( root_value=self.get_root_value(request), variable_values=variables, operation_name=operation_name, context_value=self.get_context(request), middleware=self.get_middleware(request), **extra_options, ) except Exception as e: return ExecutionResult(errors=[e], invalid=True)
def execute_graphql_request(self, request, data, query, variables, operation_name): """Execute a GraphQL request and return the result Args: request (HttpRequest): Request object from Django data (dict): Parsed content of the body of the request. query (dict): GraphQL query variables (dict): Optional variables for the GraphQL query operation_name (str): GraphQL operation name: query, mutations etc.. Returns: ExecutionResult: Execution result object from GraphQL with response or error message. """ if not query: raise HttpError( HttpResponseBadRequest("Must provide query string.")) try: backend = self.get_backend(request) document = backend.document_from_string(self.graphql_schema, query) except Exception as e: return ExecutionResult(errors=[e], invalid=True) operation_type = document.get_operation_type(operation_name) if operation_type and operation_type != "query": raise HttpError( HttpResponseBadRequest( f"'{operation_type}' is not a supported operation, Only query are supported." )) try: extra_options = {} if self.executor: # We only include it optionally since # executor is not a valid argument in all backends extra_options["executor"] = self.executor options = { "root_value": self.get_root_value(request), "variable_values": variables, "operation_name": operation_name, "context_value": self.get_context(request), "middleware": self.get_middleware(request), } options.update(extra_options) operation_type = document.get_operation_type(operation_name) return document.execute(**options) except Exception as e: return ExecutionResult(errors=[e], invalid=True)
def execute_graphql_request(self, request, query, variables, operation_name, show_graphiql=False): if not query: if show_graphiql: return None raise exceptions.ValidationError( {"message": "Must provide query string."}) try: backend = self.get_graphene_backend(request) document = backend.document_from_string(self.graphene_schema, query) except Exception as e: return ExecutionResult(errors=[e], invalid=True) if request.method.lower() == "get": operation_type = document.get_operation_type(operation_name) if operation_type and operation_type != "query": if show_graphiql: return None raise exceptions.MethodNotAllowed( method=request.method, detail="Can only perform a {} operation from a POST request." .format(operation_type), ) # Check validation self.check_document_validators(document) try: extra_options = {} if self.graphene_executor: # We only include it optionally since # executor is not a valid argument in all backends extra_options["executor"] = self.graphene_executor return document.execute( root_value=self.get_graphene_root_value(request), variable_values=variables, operation_name=operation_name, context_value=self.get_graphene_context(request), middleware=self.get_graphene_middleware(request), **extra_options) except Exception as e: return ExecutionResult(errors=[e], invalid=True)
def execute_graphql_request( self, request, data, query, variables, operation_name, ): if not query: raise HttpError( HttpResponseBadRequest("Must provide query string.")) with opentracing.global_tracer().start_active_span( "graphql_query") as scope: span = scope.span span.set_tag(opentracing.tags.COMPONENT, "GraphQL") try: document = parse(query) except GraphQLError as e: return ExecutionResult(errors=[e], data=dict(invalid=True)) if request.method.lower() == "get": operation_ast = get_operation_ast(document, operation_name) if operation_ast and operation_ast.operation != OperationType.QUERY: raise HttpError( HttpResponseNotAllowed( ["POST"], "Can only perform a {} operation from a POST request." .format(operation_ast.operation.value), )) validation_errors = validate(self.schema.graphql_schema, document) if validation_errors: return ExecutionResult(data=None, errors=validation_errors) try: with connection.execute_wrapper(tracing_wrapper): return self.schema.execute( source=query, root_value=self.get_root_value(request), variable_values=variables, operation_name=operation_name, context_value=self.get_context(request), middleware=self.get_middleware(request), ) except GraphQLError as e: span.set_tag(opentracing.tags.ERROR, True) return ExecutionResult(errors=[e])