def make_executable_schema( type_defs: Union[str, List[str]], *bindables: Union[SchemaBindable, List[SchemaBindable]], directives: Dict[str, Type[SchemaDirectiveVisitor]] = None, ) -> GraphQLSchema: if isinstance(type_defs, list): type_defs = join_type_defs(type_defs) ast_document = parse(type_defs) schema = build_and_extend_schema(ast_document) validate_schema(schema) for bindable in bindables: if isinstance(bindable, list): for obj in bindable: obj.bind_to_schema(schema) else: bindable.bind_to_schema(schema) set_default_enum_values_on_schema(schema) if directives: SchemaDirectiveVisitor.visit_schema_directives(schema, directives) assert_valid_schema(schema) return schema
def try_fast_introspection(schema: GraphQLSchema, query: str) -> Optional[ExecutionResult]: """Compute the GraphQL introspection query if query can be computed fastly. Args: schema: GraphQL schema object, obtained from the graphql library query: string containing the introspection query to be executed on the schema Returns: - GraphQL Execution Result with data = None: there were schema validation errors. - GraphQL ExecutionResult with data != None: fast introspection was successful and computed data can be found under data attribute. - None if the query does not match the set introspection query in this module: the query cannot be computed fastly with this module. """ if _remove_whitespace_from_query( query) != _whitespace_free_introspection_query: return None # Schema validations schema_validation_errors = validate_schema(schema) if schema_validation_errors: return ExecutionResult(data=None, errors=schema_validation_errors) return _execute_fast_introspection_query(schema)
def make_executable_schema( type_defs: Union[str, List[str]], bindables: Union[SchemaBindable, List[SchemaBindable], None] = None, ) -> GraphQLSchema: if isinstance(type_defs, list): type_defs = join_type_defs(type_defs) ast_document = parse(type_defs) schema = build_and_extend_schema(ast_document) validate_schema(schema) if isinstance(bindables, list): for obj in bindables: obj.bind_to_schema(schema) elif bindables: bindables.bind_to_schema(schema) set_default_enum_values_on_schema(schema) return schema
def _build_schema(self) -> GraphQLSchema: schema = build_and_extend_schema(self._all_schema()) schema_validation_errors = validate_schema(schema) if schema_validation_errors: raise Exception(f'Invalid schema: {schema_validation_errors}') schema = fix_abstract_resolve_type(schema) self._make_executable(schema) return schema
def __init__( self, # TODO: can we make sure we only allow to pass something that has been decorated? query: Type, mutation: Optional[Type] = None, subscription: Optional[Type] = None, directives=(), types=(), extensions: Sequence[Type[Extension]] = (), execution_context_class: Optional[Type[GraphQLExecutionContext]] = None, ): self.extensions = extensions self.execution_context_class = execution_context_class self.schema_converter = GraphQLCoreConverter() query_type = self.schema_converter.from_object_type(query) mutation_type = ( self.schema_converter.from_object_type(mutation) if mutation else None ) subscription_type = ( self.schema_converter.from_object_type(subscription) if subscription else None ) self.middleware: List[Middleware] = [DirectivesMiddleware(directives)] directives = [ self.schema_converter.from_directive(directive.directive_definition) for directive in directives ] self._schema = GraphQLSchema( query=query_type, mutation=mutation_type, subscription=subscription_type if subscription else None, directives=specified_directives + directives, types=list(map(self.schema_converter.from_object_type, types)), ) # Validate schema early because we want developers to know about # possible issues as soon as possible errors = validate_schema(self._schema) if errors: formatted_errors = "\n\n".join(f"❌ {error.message}" for error in errors) raise ValueError(f"Invalid Schema. Errors:\n\n{formatted_errors}") self.query = self.schema_converter.type_map[query_type.name]
def __init__( self, query: Type, mutation: Optional[Type] = None, subscription: Optional[Type] = None, scalars: Optional[GraphQLScalarMap] = None, enums: Optional[GraphQLEnumMap] = None, interfaces: Optional[GraphQLInterfaceMap] = None, query_types: Optional[GraphQLObjectTypeMap] = None, mutation_types: Optional[GraphQLInputObjectTypeMap] = None, camelcase=True, ): super().__init__() self.camelcase = camelcase builder = Builder( self.camelcase, scalars=scalars, enums=enums, interfaces=interfaces, query_types=query_types, mutation_types=mutation_types, ) query_gql, mutation_gql, subscription_gql = None, None, None if query: self.query = query fields = builder.query_fields(query) query_gql = GraphQLObjectType( "Query", fields=fields, ) if mutation: self.mutation = mutation mutation_fields = builder.query_fields(mutation) mutation_gql = GraphQLObjectType("Mutation", fields=mutation_fields) if subscription: self.subscription = subscription subscription_fields = builder.query_fields(subscription) subscription_gql = GraphQLObjectType("subscription", fields=subscription_fields) super().__init__(query_gql, mutation_gql, subscription_gql) errors = validate_schema(self) if errors: raise errors[0]
def __init__( self, # TODO: can we make sure we only allow to pass something that has been decorated? query: Type, mutation: Optional[Type] = None, subscription: Optional[Type] = None, directives=(), types=(), extensions: Sequence[Type[Extension]] = (), ): self.extensions = extensions self.type_map: Dict[str, ConcreteType] = {} query_type = get_object_type(query, self.type_map) mutation_type = get_object_type(mutation, self.type_map) if mutation else None subscription_type = (get_object_type(subscription, self.type_map) if subscription else None) self.middleware: List[Middleware] = [DirectivesMiddleware(directives)] directives = [ get_directive_type(directive, self.type_map) for directive in directives ] self._schema = GraphQLSchema( query=query_type, mutation=mutation_type, subscription=subscription_type if subscription else None, directives=specified_directives + directives, types=[get_object_type(type, self.type_map) for type in types], ) # Validate schema early because we want developers to know about # possible issues as soon as possible errors = validate_schema(self._schema) if errors: formatted_errors = "\n\n".join(f"❌ {error.message}" for error in errors) raise ValueError(f"Invalid Schema. Errors:\n\n{formatted_errors}") self.query = self.type_map[query_type.name]
def __init__( self, # TODO: can we make sure we only allow to pass something that has been decorated? query: Type, mutation: Optional[Type] = None, subscription: Optional[Type] = None, directives=(), types=(), extensions: Sequence[Union[Type[Extension], Extension]] = (), execution_context_class: Optional[Type[GraphQLExecutionContext]] = None, config: Optional[StrawberryConfig] = None, scalar_overrides: Optional[ Dict[object, Union[ScalarWrapper, ScalarDefinition]] ] = None, ): self.extensions = extensions self.execution_context_class = execution_context_class self.config = config or StrawberryConfig() scalar_registry: Dict[object, Union[ScalarWrapper, ScalarDefinition]] = { **DEFAULT_SCALAR_REGISTRY } if scalar_overrides: scalar_registry.update(scalar_overrides) self.schema_converter = GraphQLCoreConverter(self.config, scalar_registry) self.directives = directives query_type = self.schema_converter.from_object(query._type_definition) mutation_type = ( self.schema_converter.from_object(mutation._type_definition) if mutation else None ) subscription_type = ( self.schema_converter.from_object(subscription._type_definition) if subscription else None ) directives = [ self.schema_converter.from_directive(directive.directive_definition) for directive in directives ] graphql_types = [] for type_ in types: graphql_type = self.schema_converter.from_object(type_._type_definition) graphql_types.append(graphql_type) self._schema = GraphQLSchema( query=query_type, mutation=mutation_type, subscription=subscription_type if subscription else None, directives=specified_directives + directives, types=graphql_types, ) # Validate schema early because we want developers to know about # possible issues as soon as possible errors = validate_schema(self._schema) if errors: formatted_errors = "\n\n".join(f"❌ {error.message}" for error in errors) raise ValueError(f"Invalid Schema. Errors:\n\n{formatted_errors}") self.query = self.schema_converter.type_map[query_type.name]
def test_convert_manager(info, session, manager_collection): converted = Convert(manager_collection.manager_map.values()) converted_schema = converted.generate_schema() schema_validator = validate_schema(converted_schema) assert schema_validator == [] assert assert_valid_schema(converted_schema) is None
async def __call__(self, request: Request) -> Response: """ Run the GraphQL query provided. :param request: aiohttp Request :return: aiohttp Response """ request_method = request.method.lower() try: variables = json.loads(request.query.get("variables", "{}")) except json.decoder.JSONDecodeError: return self.error_response("Variables are invalid JSON.") operation_name = request.query.get("operationName") if request_method == "options": return self.process_preflight(request) elif request_method == "post": try: data = await self.parse_body(request) except json.decoder.JSONDecodeError: return self.error_response("POST body sent invalid JSON.") operation_name = data.get("operationName", operation_name) elif request_method == "get": data = {"query": request.query.get("query")} else: return self.error_response( "GraphQL only supports GET and POST requests.", 405, headers={"Allow": "GET, POST"}, ) is_tool = self.is_tool(request) vars_dyn = data.get("variables", {}) or {} variables.update( vars_dyn if isinstance(vars_dyn, dict) else json.loads(vars_dyn) ) query = cast(str, data.get("query")) context = self.get_context(request) invalid = False if is_tool: tool = cast(GraphQLTool, self.tool) return await tool.render(query, variables, operation_name) if not data.get("query"): return self.encode_response( request, ExecutionResult( data=None, errors=[GraphQLError(message="Must provide query string.")], ), invalid=True, ) # Validate Schema schema_validation_errors = validate_schema(self.schema) if schema_validation_errors: # pragma: no cover return self.encode_response( request, ExecutionResult(data=None, errors=schema_validation_errors), invalid=True, ) # Parse try: document = parse(query) op = get_operation_ast(document, operation_name) if op is None: invalid = True else: if request_method == "get" and op.operation != OperationType.QUERY: return self.error_response( "Can only perform a {} operation from a POST request.".format( op.operation.value ), 405, headers={"Allow": "POST"}, ) except GraphQLError as error: return self.encode_response( request, ExecutionResult(data=None, errors=[error]), invalid=True ) except Exception as error: # pragma: no cover error = GraphQLError(str(error), original_error=error) return self.encode_response( request, ExecutionResult(data=None, errors=[error]), invalid=True ) # Validate validation_errors = validate(self.schema, document) if validation_errors: return self.encode_response( request, ExecutionResult(data=None, errors=validation_errors), invalid=True, ) if self.asynchronous: result = self._graphql( self.schema, document=document, variable_values=variables, operation_name=operation_name, root_value=self.root_value, context_value=context, middleware=self.middleware, ) if isawaitable(result): # pragma: no branch result = await cast(Awaitable[ExecutionResult], result) else: result = self._graphql( self.schema, document=document, variable_values=variables, operation_name=operation_name, root_value=self.root_value, context_value=context, middleware=self.middleware, ) return self.encode_response( request, cast(ExecutionResult, result), invalid=invalid )