106 lines
3.5 KiB
Python
106 lines
3.5 KiB
Python
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,
|
|
)
|