from typing import cast, Union from ..language import DocumentNode, Source, parse from ..type import ( GraphQLObjectType, GraphQLSchema, GraphQLSchemaKwargs, specified_directives, ) from .extend_schema import ExtendSchemaImpl __all__ = [ "build_ast_schema", "build_schema", ] def build_ast_schema( document_ast: DocumentNode, assume_valid: bool = False, assume_valid_sdl: bool = False, ) -> GraphQLSchema: """Build a GraphQL Schema from a given AST. This takes the ast of a schema document produced by the parse function in src/language/parser.py. If no schema definition is provided, then it will look for types named Query, Mutation and Subscription. Given that AST it constructs a GraphQLSchema. The resulting schema has no resolve methods, so execution will use default resolvers. When building a schema from a GraphQL service's introspection result, it might be safe to assume the schema is valid. Set ``assume_valid`` to ``True`` to assume the produced schema is valid. Set ``assume_valid_sdl`` to ``True`` to assume it is already a valid SDL document. """ if not isinstance(document_ast, DocumentNode): raise TypeError("Must provide valid Document AST.") if not (assume_valid or assume_valid_sdl): from ..validation.validate import assert_valid_sdl assert_valid_sdl(document_ast) empty_schema_kwargs = GraphQLSchemaKwargs( query=None, mutation=None, subscription=None, description=None, types=(), directives=(), extensions={}, ast_node=None, extension_ast_nodes=(), assume_valid=False, ) schema_kwargs = ExtendSchemaImpl.extend_schema_args( empty_schema_kwargs, document_ast, assume_valid ) if not schema_kwargs["ast_node"]: for type_ in schema_kwargs["types"] or (): # Note: While this could make early assertions to get the correctly # typed values below, that would throw immediately while type system # validation with validate_schema() will produce more actionable results. type_name = type_.name if type_name == "Query": schema_kwargs["query"] = cast(GraphQLObjectType, type_) elif type_name == "Mutation": schema_kwargs["mutation"] = cast(GraphQLObjectType, type_) elif type_name == "Subscription": schema_kwargs["subscription"] = cast(GraphQLObjectType, type_) # If specified directives were not explicitly declared, add them. directives = schema_kwargs["directives"] directive_names = set(directive.name for directive in directives) missing_directives = [] for directive in specified_directives: if directive.name not in directive_names: missing_directives.append(directive) if missing_directives: schema_kwargs["directives"] = directives + tuple(missing_directives) return GraphQLSchema(**schema_kwargs) def build_schema( source: Union[str, Source], assume_valid: bool = False, assume_valid_sdl: bool = False, no_location: bool = False, allow_legacy_fragment_variables: bool = False, ) -> GraphQLSchema: """Build a GraphQLSchema directly from a source document.""" return build_ast_schema( parse( source, no_location=no_location, allow_legacy_fragment_variables=allow_legacy_fragment_variables, ), assume_valid=assume_valid, assume_valid_sdl=assume_valid_sdl, )