def build_and_extend_schema(ast: DocumentNode) -> GraphQLSchema: schema = build_ast_schema(ast) extension_ast = extract_extensions(ast) if extension_ast.definitions: schema = extend_schema(schema, extension_ast) return schema
def update_schema(schema, extension): logger.debug("Extending base schema with:\n%s" % extension) schema = graphql.extend_schema(schema, graphql.parse(extension)) tables = schema_to_tables(extension) for (table, columns) in tables.items(): schema = add_type_fields(schema, table, columns) schema = add_type_mutators(schema, table, columns) return schema
def make_schema( type_defs: Union[str, List[str]], assume_valid: bool = False, assume_valid_sdl: bool = False, no_location: bool = False, experimental_fragment_variables: bool = False, federation: bool = False, directives: Dict[str, Type[SchemaDirectiveVisitor]] = None, ) -> GraphQLSchema: if isinstance(type_defs, list): type_defs = join_type_defs(type_defs) if federation: # Remove custom schema directives (to avoid apollo-gateway crashes). sdl = purge_schema_directives(type_defs) # remove subscription because Apollo Federation not support subscription yet. # type_defs = remove_subscription(type_defs) type_defs = join_type_defs([type_defs, federation_service_type_defs]) schema = build_schema( type_defs, assume_valid, assume_valid_sdl, no_location, experimental_fragment_variables ) entity_types = get_entity_types(schema) if entity_types: schema = extend_schema(schema, parse(federation_entity_type_defs)) # Add _entities query. entity_type = schema.get_type("_Entity") if entity_type: entity_type = cast(GraphQLUnionType, entity_type) entity_type.types = entity_types query_type = schema.get_type("Query") if query_type: query_type = cast(GraphQLObjectType, query_type) query_type.fields["_entities"].resolve = resolve_entities # Add _service query. query_type = schema.get_type("Query") if query_type: query_type = cast(GraphQLObjectType, query_type) query_type.fields["_service"].resolve = lambda _service, info: {"sdl": sdl} else: schema = build_schema( type_defs, assume_valid, assume_valid_sdl, no_location, experimental_fragment_variables ) if directives: SchemaDirectiveVisitor.visit_schema_directives(schema, directives) return schema
def add_type_mutators(schema, table, columns): column_str = ", ".join( "%s: %s" % column for column in columns[1:]) # omits the id field that's always first addAttr = "add{table} ({columns}): String".format( table=table, columns=column_str ) # These always return the ID created or null for errors mutations = "extend type Mutation { %s }" % addAttr schema = graphql.extend_schema(schema, graphql.parse(mutations)) schema.mutation_type.fields[ "add%s" % table].resolve = resolvers.meta_create_attribute(table) return schema
def make_remote_executable_schema(schema, client): # Get a generic resolver for this client. sync_resolver = create_sync_resolver(client) # Get a deep copy of the schema by extending it with an empty ASST. noopdoc = graphql.language.ast.Document([]) schema = graphql.extend_schema(schema, documentAST=noopdoc) query_type = schema.get_query_type() if query_type is not None: for key, value in query_type.fields.items(): value.resolver = create_sync_resolver(client) mutation_type = schema.get_mutation_type() if mutation_type is not None: for key, value in mutation_type.fields.items(): value.resolver = sync_resolver subscription_type = schema.get_subscription_type() if subscription_type is not None: # Two things preventing us from proxying subscriptions: # - [ ] gql.Client does not expose subscriptions over websockets # - [ ] need ability to stick with datasub's own subscriptions raise NotImplementedError("Schema with subscription type.") # Add missing abstract resolvers (scalar, unions, interfaces, ...) for key, value in schema.get_type_map().items(): if hasattr(value, 'resolve_type'): value.resolve_type = typename_resolver elif isinstance(value, graphql.GraphQLScalarType): value.serialize = lambda x: x value.parse_value = lambda x: x value.parse_literal = lambda x: x elif isinstance(value, graphql.GraphQLObjectType): if not value.name.startswith("__") and value not in ( query_type, mutation_type, subscription_type): for k, v in value.fields.items(): v.resolver = default_merged_resolver elif hasattr(value, 'resolver'): raise NotImplementedError( "Missing resolver replacement for %s: %s." % (key, value)) return schema
def extend_federated_schema( schema: GraphQLSchema, document_ast: DocumentNode, assume_valid: bool = False, assume_valid_sdl: bool = False, ) -> GraphQLSchema: extended_schema = extend_schema( schema, document_ast, assume_valid, assume_valid_sdl, ) for (k, v) in schema.type_map.items(): resolve_reference = getattr(v, "__resolve_reference__", None) if resolve_reference and k in extended_schema.type_map: setattr( extended_schema.type_map[k], "__resolve_reference__", resolve_reference, ) return extended_schema
def build_and_extend_schema( type_defs: typing.Union[ typing.List[str], typing.List[DocumentNode], typing.Iterator[DocumentNode], ], ) -> GraphQLSchema: document_list = [maybe_parse(type_def) for type_def in type_defs] ast_document = concat_ast(document_list) ast_document = assert_has_query_and_mutation(ast_document) schema = build_ast_schema(ast_document) extension_ast = extract_extensions(ast_document) if extension_ast.definitions: LOG.debug(f'Extending schema') schema = extend_schema(schema, extension_ast) return schema
# We need to have a root query that we can extend, according to th SDL spec # we can not have an empty query type. So we initialize it with `_empty` which # will never get used. root_query = GraphQLObjectType("Query", {"_empty": GraphQLField(GraphQLString)}) # In order to extend the schema we need to start with a valid schema # class instance. In graphql-core-next we can use a SDL file for the root # as well. Here we need a little hack to future proof the rest of our # application structure. root_schema = GraphQLSchema(query=root_query) BASE_DIR = os.path.dirname(os.path.abspath(__file__)) schema_files = os.listdir(os.path.join(BASE_DIR, 'gql')) schema_files.sort() for filename in schema_files: with open(os.path.join(BASE_DIR, 'gql', filename)) as schema_file: schema_data = schema_file.read() # Each time we extend the root schema it makes a copy and returns # the newly extended schema and the orginal is unchanged. root_schema = extend_schema(root_schema, parse(schema_data)) # Since extend_schema parses client schema you'll get an error if you attempt # to execute it: 'Client Schema cannot be used for execution.' # Printing out the full schema and then parsing it avoids this issue. fully_extended_schema_sdl = print_schema(root_schema) schema = build_ast_schema(parse(fully_extended_schema_sdl))
# By extending the types you can spread the schema across multiple files # for easier management. You can also have different endpoints only use # a subset of your schema if you break it up. EXTENDED = """ type User { name: String last: String friend: User } extend type Query { hello(name: String): User } """ schema = build_schema(ROOT_QUERY) extended_schema = extend_schema(schema, parse(EXTENDED)) # repeat as needed sample_query = """{ hello(name: "frank") { name last } } """ class User: def __init__(self, name): self.name = name
def insert_builtins(schema): for scalar in BUILTIN_SCALARS: if not schema.get_type(scalar): schema = graphql.extend_schema(schema, graphql.parse(f"scalar {scalar}")) return schema
extend type Query { getCommitCalendar(username: String): CommitCalendar } """ root_query = GraphQLObjectType( "Query", {"_empty": GraphQLField(GraphQLString)} ) root_schema = GraphQLSchema( query=root_query ) extenders = extend_schema(root_schema, parse(EXTENDED)) extended_schema = build_ast_schema(parse(print_schema(extenders))) # repeat as needed print(dir(extended_schema)) print(extended_schema.get_type_map()) print(dir(extended_schema.get_type('Query'))) query = extended_schema.get_type('Query') for field, obj in query.fields.items(): print(obj.resolver) print(dir(obj)) sample_query = """{ getCommitCalendar(username: "******") { start
from ariadne.asgi import GraphQL from graphql import extend_schema from fastapi import FastAPI from nomine.db import init_db, Session, Base from graphql_sqlalchemy import build_schema from .api import schema as api_schema, bindables app = FastAPI(debug=True) init_db() session = Session() schema = build_schema(Base) schema = extend_schema(schema, api_schema) for bindable in bindables: bindable.bind_to_schema(schema) app.mount("/graphql", GraphQL(schema, context_value=dict(session=session)))
from graphql import extend_schema, parse document = parse( """ type Query { me: User } type User { id: ID name: String } """, no_location=True, ) schema = extend_schema( document, parse(""" extend type User { lastName: String } """), ) # https://graphql-core-next.readthedocs.io/en/latest/usage/extension.html
@property def tooltip(self): if not self.enabled: return 'You do not have permission to do this!' def computeServerActions(_source, info): actions = [] for action in SERVER_ACTION_LIST: enabled = info.context.user.has_permission_to_do_action(action) actions.append(action(enabled=enabled)) return actions schema = build_schema(ROOT_QUERY) schema = extend_schema(schema, parse(EXTENDED)) query = """ { hello(name: "frank") { name last } } """ class Resource: pass