def formats_graphql_error(): path: List[Union[int, str]] = ["one", 2] extensions = {"ext": None} error = GraphQLError( "test message", Node(), Source(""" query { something } """), [16, 41], ["one", 2], ValueError("original"), extensions=extensions, ) assert error.formatted == { "message": "test message", "locations": [{ "line": 2, "column": 16 }, { "line": 3, "column": 17 }], "path": path, "extensions": extensions, }
def get_nodes(ids, graphene_type=None): """Get a list of nodes. If the `graphene_type` argument is provided, the IDs will be validated against this type. If the type was not provided, it will be looked up in the Graphene's registry. Raises an error if not all IDs are of the same type. """ nodes_type, pks = _resolve_nodes(ids, graphene_type) # If `graphene_type` was not provided, check if all resolved types are # the same. This prevents from accidentally mismatching IDs of different # types. if nodes_type and not graphene_type: graphene_type = _resolve_graphene_type(nodes_type) nodes = list(graphene_type._meta.model.objects.filter(pk__in=pks)) nodes.sort(key=lambda e: pks.index(str(e.pk))) # preserve order in pks if not nodes: # pragma: no cover raise GraphQLError( "Could not resolve to a node with the id list of '{}'.".format( ids, ), ) nodes_pk_list = [str(node.pk) for node in nodes] for pk in pks: if pk not in nodes_pk_list: # pragma: no cover raise AssertionError( "There is no node of type {} with pk {}".format( graphene_type, pk, )) return nodes
def get_nodes(ids, graphene_type=None, qs=None): """Return a list of nodes. If the `graphene_type` argument is provided, the IDs will be validated against this type. If the type was not provided, it will be looked up in the Graphene's registry. Raises an error if not all IDs are of the same type. """ nodes_type, pks = _resolve_nodes(ids, graphene_type) # If `graphene_type` was not provided, check if all resolved types are # the same. This prevents from accidentally mismatching IDs of different # types. if nodes_type and not graphene_type: graphene_type = _resolve_graphene_type(nodes_type) if qs is None: qs = graphene_type._meta.model.objects nodes = list(qs.filter(pk__in=pks)) nodes.sort(key=lambda e: pks.index(str(e.pk))) # preserve order in pks if not nodes: raise GraphQLError(ERROR_COULD_NO_RESOLVE_GLOBAL_ID % ids) nodes_pk_list = [str(node.pk) for node in nodes] for pk in pks: assert pk in nodes_pk_list, "There is no node of type {} with pk {}".format( graphene_type, pk ) return nodes
def format_error(error): if isinstance(error, GraphQLLocatedError): try: error_dict = json.loads(str(error)) except: return GraphQLView.format_error(GraphQLError("Resolver error")) return GraphQLView.format_error(error)
def _resolve_nodes(ids, graphene_type=None): pks = [] invalid_ids = [] used_type = graphene_type for graphql_id in ids: if not graphql_id: continue try: node_type, _id = from_global_id(graphql_id) except Exception: invalid_ids.append(graphql_id) continue if used_type: if str(used_type) != node_type: raise AssertionError("Must receive a {} id.".format( str(used_type))) used_type = node_type pks.append(_id) if invalid_ids: # pragma: no cover raise GraphQLError( "Could not resolve to a node with the id list of '{}'.".format( invalid_ids, ), ) return used_type, pks
def default_error_formatter_includes_path(): path = ["path", 3, "to", "field"] # noinspection PyArgumentEqualDefault e = GraphQLError("msg", None, None, None, path) formatted = format_error(e) assert formatted == e.formatted assert formatted == {"message": "msg", "locations": None, "path": path}
def serializes_to_include_path(): path = ["path", 3, "to", "field"] # noinspection PyArgumentEqualDefault e = GraphQLError("msg", None, None, None, path) assert e.path is path assert repr(e) == ("GraphQLError('msg'," " path=['path', 3, 'to', 'field'])")
def format_error(cls, error): if isinstance(error, GraphQLError): result = format_graphql_error(error) else: result = {"message": str(error)} if "extensions" not in result: result["extensions"] = {} exc = error while isinstance(exc, GraphQLError) and hasattr(exc, "original_error"): exc = exc.original_error if isinstance(exc, AssertionError): exc = GraphQLError(str(exc)) if isinstance(exc, cls.HANDLED_EXCEPTIONS): handled_errors_logger.info("A query had an error", exc_info=exc) else: unhandled_errors_logger.error("A query failed unexpectedly", exc_info=exc) result["extensions"]["exception"] = {"code": type(exc).__name__} if settings.DEBUG: lines = [] if isinstance(exc, BaseException): for line in traceback.format_exception( type(exc), exc, exc.__traceback__ ): lines.extend(line.rstrip().splitlines()) result["extensions"]["exception"]["stacktrace"] = lines return result
def serializes_to_include_message_and_locations(): e = GraphQLError("msg", field_node) assert "msg" in str(e) assert "(2:3)" in str(e) assert repr(e) == ( "GraphQLError('msg', locations=[SourceLocation(line=2, column=3)])" )
def __init__(self, query=None, query_id=None, operation_name=None, variables=None): if not query or query_id: raise GraphQLError("Must provide query string.") if variables and not isinstance(variables, Mapping): raise GraphQLError( "variables, if provided need to be a mapping. Received {}.". format(repr(variables))) self.query = query self.query_id = query_id self.operation_name = operation_name self.variables = variables or {}
def includes_extension_fields(): error = GraphQLError("msg", extensions={"foo": "bar"}) assert error.formatted == { "message": "msg", "extensions": { "foo": "bar" }, }
def resolve_filter_suppliers(self, info, **kwargs): for key in kwargs: if kwargs[key] == "": message = ORDERS_ERROR_RESPONSES["supplier_search_key_error"] raise GraphQLError(message) kwargs[key] = kwargs[key].strip() \ if key == "name__icontains" else kwargs[key] user = info.context.user supplier = Suppliers.objects.filter( **kwargs, business=user.active_outlet.business, parent=None) if not supplier: message = ORDERS_ERROR_RESPONSES[ "inexistent_supplier_search_error"] raise GraphQLError(message) return supplier
def on_resolve(payload): try: payload.clientMutationId = input_['clientMutationId'] except Exception: raise GraphQLError( 'Cannot set clientMutationId in the payload object {}'. format(repr(payload))) return payload
def serializes_to_include_message_and_locations(): # noinspection PyUnresolvedReferences node = parse('{ field }').definitions[0].selection_set.selections[0] e = GraphQLError('msg', [node]) assert 'msg' in str(e) assert '(1:3)' in str(e) assert repr(e) == ("GraphQLError('msg'," " locations=[SourceLocation(line=1, column=3)])")
def converts_source_and_positions_to_locations(): source = Source('{\n field\n}') # noinspection PyArgumentEqualDefault e = GraphQLError('msg', None, source, [10]) assert e.nodes is None assert e.source is source assert e.positions == [10] assert e.locations == [(2, 9)]
def passes_the_cause_of_an_original_error(): cause = ValueError("cause") try: raise RuntimeError("effect") from cause except RuntimeError as runtime_error: original = runtime_error e = GraphQLError("msg", original_error=original) assert e.__cause__ is cause
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) 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 get_nodes( ids, graphene_type: Union[graphene.ObjectType, str] = None, model=None, qs=None, schema=None, ): """Return a list of nodes. If the `graphene_type` argument is provided, the IDs will be validated against this type. If the type was not provided, it will be looked up in the schema. Raises an error if not all IDs are of the same type. If the `graphene_type` is of type str, the model keyword argument must be provided. """ nodes_type, pks = resolve_global_ids_to_primary_keys(ids, graphene_type, raise_error=True) # If `graphene_type` was not provided, check if all resolved types are # the same. This prevents from accidentally mismatching IDs of different # types. if nodes_type and not graphene_type: if schema: graphene_type = _resolve_graphene_type(schema, nodes_type) else: raise GraphQLError("GraphQL schema was not provided") if qs is None and graphene_type and not isinstance(graphene_type, str): qs = graphene_type._meta.model.objects elif model is not None: qs = model.objects nodes = list(qs.filter(pk__in=pks)) nodes.sort(key=lambda e: pks.index(str(e.pk))) # preserve order in pks if not nodes: raise GraphQLError(ERROR_COULD_NO_RESOLVE_GLOBAL_ID % ids) nodes_pk_list = [str(node.pk) for node in nodes] for pk in pks: assert pk in nodes_pk_list, "There is no node of type {} with pk {}".format( graphene_type, pk) return nodes
def converts_node_with_loc_start_zero_to_positions_and_locations(): source = Source('{\n field\n}') ast = parse(source) operations_node = ast.definitions[0] e = GraphQLError('msg', [operations_node]) assert e.nodes == [operations_node] assert e.source is source assert e.positions == [0] assert e.locations == [(1, 1)]
def parse_literal(node): weight = None if isinstance(node, ast.ObjectValue): weight = WeightScalar.parse_literal_object(node) else: weight = WeightScalar.parse_decimal(node.value) if not weight: raise GraphQLError(f"Unsupported value: {node.value}") return weight
def parse_value(value): weight = None if isinstance(value, dict): weight = Weight(**{value["unit"]: value["value"]}) else: weight = WeightScalar.parse_decimal(value) if not weight: raise GraphQLError(f"Unsupported value: {value}") return weight
def prints_an_error_with_nodes_from_different_sources(): doc_a = parse( Source( dedent( """ type Foo { field: String } """ ), "SourceA", ) ) op_a = doc_a.definitions[0] op_a = cast(ObjectTypeDefinitionNode, op_a) assert op_a and op_a.kind == "object_type_definition" and op_a.fields field_a = op_a.fields[0] doc_b = parse( Source( dedent( """ type Foo { field: Int } """ ), "SourceB", ) ) op_b = doc_b.definitions[0] op_b = cast(ObjectTypeDefinitionNode, op_b) assert op_b and op_b.kind == "object_type_definition" and op_b.fields field_b = op_b.fields[0] error = GraphQLError( "Example error with two nodes", [field_a.type, field_b.type] ) printed_error = print_error(error) assert printed_error + "\n" == dedent( """ Example error with two nodes SourceA:2:10 1 | type Foo { 2 | field: String | ^ 3 | } SourceB:2:10 1 | type Foo { 2 | field: Int | ^ 3 | } """ ) assert str(error) == printed_error
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 uses_default_message(): # noinspection PyTypeChecker formatted = format_error(GraphQLError(None)) # type: ignore assert formatted == { "message": "An unknown error occurred.", "locations": None, "path": None, }
def test_strawberry_logger_error(caplog): caplog.set_level(logging.ERROR, logger="strawberry.execution") exc = GraphQLError("test exception") StrawberryLogger.error(exc) assert caplog.record_tuples == [ ("strawberry.execution", logging.ERROR, "test exception") ]
def parse_money_literal(value_node: ValueNode, variables=None) -> Money: money = value_from_ast_untyped(value_node, variables) if variables is not None and ( # variables are not set when checked with ValuesOfCorrectTypeRule not money or not is_finite(money.get("amount")) or not isinstance(money.get("currency"), str)): raise GraphQLError("Cannot parse literal money value: " + inspect(money)) return Money(**money)
def parse_datetime_literal( value_node: ValueNode, variables: Optional[Dict[str, Any]] = None) -> datetime: ast_value = value_from_ast_untyped(value_node, variables) if not isinstance(ast_value, str): raise GraphQLError("Cannot parse literal datetime value: " + inspect(ast_value)) return parse_datetime_value(ast_value)
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 check_if_query_contains_only_schema(self, document: GraphQLDocument): for definition in document.document_ast.definitions: selections = definition.selection_set.selections if len(selections) > 1: for selection in selections: selection_name = str(selection.name.value) if selection_name == "__schema": msg = "`__schema` must be fetched in separete query" raise GraphQLError(msg)
def get_node(cls, info, id): try: inst = cls._meta.model.objects.get(pk=id) except cls._meta.model.DoesNotExist: raise GraphQLError( "Requested {cls._meta.model.__name__} instance does not exist." ) cls.ensure_user_can_view_instance(info, inst) return inst