def build_schema(config, engine, subset=None): """ Build the object types for all the indexes. Subset is a list of index names that the schema should include. If no subset is provided, then all indexes are built and added to the schema. """ fields = {} for i in Index.list_indexes(engine): if not subset or i.name in subset: try: output_type, args = build_index_type(config, engine, i) resolver = ql_resolver(config, engine, i) # create the field for this table, with arguments and resolver fields[f'{i.table.name}'] = graphql.GraphQLField( graphql.GraphQLList(output_type), args=args, resolve=resolver, ) except (ValueError, AssertionError) as ex: logging.error('%s; skipping %s...', str(ex), i.name) # construct the query object for the root object type root = graphql.GraphQLObjectType('Query', fields) # build the schema return graphql.GraphQLSchema(query=root)
def _create_graphql_schema(query_type, mutation_type): graphql_query_type = to_graphql_type(query_type).of_type if mutation_type is None: graphql_mutation_type = None else: graphql_mutation_type = to_graphql_type(query_type).of_type return graphql.GraphQLSchema( query=graphql_query_type, mutation=graphql_mutation_type, )
def build(self, **options): self._root_context.update(options) queries = list(map(query, self._queries)) mutations = list(map(mutation, self._mutations)) subscriptions = list(map(subscription, self._subscriptions)) extra_types = [ self.transformer.transform(t, allow_null=True) for t in self._types ] return graphql.GraphQLSchema( query=self.transformer.transform( generate_root_type(queries, name="Query"), allow_null=True) if queries else None, mutation=self.transformer.transform( generate_root_type(mutations, name="Mutation"), allow_null=True) if mutations else None, subscription=self.transformer.transform( generate_root_type(subscriptions, name="Subscription"), allow_null=True) if subscriptions else None, types=extra_types, )
def graphql_schema( *, query: Iterable[Union[Callable, Query]] = (), mutation: Iterable[Union[Callable, Mutation]] = (), subscription: Iterable[Union[Callable[..., AsyncIterable], Subscription]] = (), types: Iterable[Type] = (), directives: Optional[Collection[graphql.GraphQLDirective]] = None, description: Optional[str] = None, extensions: Optional[Dict[str, Any]] = None, aliaser: Optional[Aliaser] = to_camel_case, enum_aliaser: Optional[Aliaser] = str.upper, enum_schemas: Optional[Mapping[Enum, Schema]] = None, id_types: Union[Collection[AnyType], IdPredicate] = (), id_encoding: Tuple[Optional[Callable[[str], Any]], Optional[Callable[[Any], str]]] = (None, None), # TODO deprecate union_ref parameter union_ref: UnionNameFactory = "Or".join, union_name: UnionNameFactory = "Or".join, default_deserialization: DefaultConversion = None, default_serialization: DefaultConversion = None, ) -> graphql.GraphQLSchema: if aliaser is None: aliaser = settings.aliaser if enum_aliaser is None: enum_aliaser = lambda s: s if default_deserialization is None: default_deserialization = settings.deserialization.default_conversion if default_serialization is None: default_serialization = settings.serialization.default_conversion query_fields: List[ResolverField] = [] mutation_fields: List[ResolverField] = [] subscription_fields: List[ResolverField] = [] for operations, op_class, fields in [ (query, Query, query_fields), (mutation, Mutation, mutation_fields), ]: for operation in operations: # type: ignore alias, resolver = operation_resolver(operation, op_class) resolver_field = ResolverField( alias, resolver, resolver.types(), resolver.parameters, resolver.parameters_metadata, ) fields.append(resolver_field) for sub_op in subscription: # type: ignore if not isinstance(sub_op, Subscription): sub_op = Subscription(sub_op) # type: ignore sub_parameters: Sequence[Parameter] if sub_op.resolver is not None: alias = sub_op.alias or sub_op.resolver.__name__ _, subscriber2 = operation_resolver(sub_op, Subscription) _, *sub_parameters = resolver_parameters(sub_op.resolver, check_first=False) resolver = Resolver( sub_op.resolver, sub_op.conversion, sub_op.schema, subscriber2.error_handler, sub_parameters, sub_op.parameters_metadata, ) sub_types = resolver.types() subscriber = replace(subscriber2, error_handler=None) subscribe = resolver_resolve( subscriber, subscriber.types(), aliaser, default_deserialization, default_serialization, serialized=False, ) else: alias, subscriber2 = operation_resolver(sub_op, Subscription) resolver = Resolver( lambda _: _, sub_op.conversion, sub_op.schema, subscriber2.error_handler, (), {}, ) subscriber = replace(subscriber2, error_handler=None) sub_parameters = subscriber.parameters sub_types = subscriber.types() if get_origin2(sub_types["return"]) not in async_iterable_origins: raise TypeError( "Subscriptions must return an AsyncIterable/AsyncIterator") event_type = get_args2(sub_types["return"])[0] subscribe = resolver_resolve( subscriber, sub_types, aliaser, default_deserialization, default_serialization, serialized=False, ) sub_types = { **sub_types, "return": resolver.return_type(event_type) } resolver_field = ResolverField( alias, resolver, sub_types, sub_parameters, sub_op.parameters_metadata, subscribe, ) subscription_fields.append(resolver_field) is_id = id_types.__contains__ if isinstance(id_types, Collection) else id_types if id_encoding == (None, None): id_type: graphql.GraphQLScalarType = graphql.GraphQLID else: id_deserializer, id_serializer = id_encoding id_type = graphql.GraphQLScalarType( name="ID", serialize=id_serializer or graphql.GraphQLID.serialize, parse_value=id_deserializer or graphql.GraphQLID.parse_value, parse_literal=graphql.GraphQLID.parse_literal, description=graphql.GraphQLID.description, ) output_builder = OutputSchemaBuilder( aliaser, enum_aliaser, enum_schemas or {}, default_serialization, id_type, is_id, union_name or union_ref, default_deserialization, ) def root_type( name: str, fields: Sequence[ResolverField] ) -> Optional[graphql.GraphQLObjectType]: if not fields: return None tp, type_name = type(name, (), {}), TypeName(graphql=name) return output_builder.object(tp, (), fields).merge( type_name, None).raw_type # type: ignore return graphql.GraphQLSchema( query=root_type("Query", query_fields), mutation=root_type("Mutation", mutation_fields), subscription=root_type("Subscription", subscription_fields), types=[output_builder.visit(cls).raw_type for cls in types], # type: ignore directives=directives, description=description, extensions=extensions, )
class Root: def __init__(self, data): self.data = data def person(self, info, *, name: t.Optional[str] = None) -> Person: if name is None: return None for row in self.data["people"]: if name == row["name"]: return row return None schema = g.GraphQLSchema(query_type) @as_command def run(): q = """\ { foo: person(name: "foo") { name, age, nickname } xxx: person(name: "xxx") { name, age, nickname } } """ data = { "people": [ {"name": "boo", "age": 20}, {"name": "foo", "age": 20, "nickname": "F"},
import graphql from graphql.utilities import print_schema Person = graphql.GraphQLObjectType( "Person", lambda: { "name": graphql.GraphQLField(graphql.GraphQLNonNull(graphql.GraphQLString, )), }, ) Query = graphql.GraphQLObjectType( "Query", lambda: { "people": graphql.GraphQLField( graphql.GraphQLNonNull(graphql.GraphQLList(Person))) }, ) schema = graphql.GraphQLSchema(Query) print(print_schema(schema)) # or graphql.print_schema(schema)
def create_graphql_schema(query_type, mutation_type, types=None): if types is None: types = () graphql_types = {} def to_graphql_type(graph_type): if graph_type not in graphql_types: graphql_types[graph_type] = generate_graphql_type(graph_type) return graphql_types[graph_type] def generate_graphql_type(graph_type): if graph_type == schema.Boolean: return graphql.GraphQLNonNull(graphql.GraphQLBoolean) elif graph_type == schema.Float: return graphql.GraphQLNonNull(graphql.GraphQLFloat) elif graph_type == schema.Int: return graphql.GraphQLNonNull(graphql.GraphQLInt) elif graph_type == schema.String: return graphql.GraphQLNonNull(graphql.GraphQLString) elif isinstance(graph_type, schema.EnumType): # TODO: should enums map names or values? values = iterables.to_dict( (member.value, graphql.GraphQLEnumValue(member.value)) for member in graph_type.enum) graphql_type = graphql.GraphQLEnumType(graph_type.name, values=values) return graphql.GraphQLNonNull(graphql_type) elif isinstance(graph_type, schema.InputObjectType): return graphql.GraphQLNonNull( graphql.GraphQLInputObjectType( name=graph_type.name, fields=lambda: iterables.to_dict( (snake_case_to_camel_case(field.name), to_graphql_input_field(field)) for field in graph_type.fields), )) elif isinstance(graph_type, schema.InterfaceType): return graphql.GraphQLNonNull( graphql.GraphQLInterfaceType( name=graph_type.name, fields=to_graphql_fields(graph_type.fields), resolve_type=lambda: None, )) elif isinstance(graph_type, schema.ListType): return graphql.GraphQLNonNull( graphql.GraphQLList(to_graphql_type(graph_type.element_type))) elif isinstance(graph_type, schema.NullableType): return to_graphql_type(graph_type.element_type).of_type elif isinstance(graph_type, schema.ObjectType): return graphql.GraphQLNonNull( graphql.GraphQLObjectType( name=graph_type.name, fields=to_graphql_fields(graph_type.fields), interfaces=tuple( to_graphql_type(interface).of_type for interface in graph_type.interfaces), )) else: raise ValueError("unsupported type: {}".format(graph_type)) def to_graphql_input_field(graph_field): graphql_type = to_graphql_type(graph_field.type) if graph_field.has_default and isinstance(graphql_type, graphql.GraphQLNonNull): graphql_type = graphql_type.of_type return graphql.GraphQLInputField(type_=graphql_type) def to_graphql_fields(graph_fields): return lambda: iterables.to_dict( (snake_case_to_camel_case(field.name), to_graphql_field(field)) for field in graph_fields) def to_graphql_field(graph_field): return graphql.GraphQLField( type_=to_graphql_type(graph_field.type), args=iterables.to_dict((snake_case_to_camel_case(param.name), to_graphql_argument(param)) for param in graph_field.params), ) def to_graphql_argument(param): graphql_type = to_graphql_type(param.type) if param.has_default and isinstance(graphql_type, graphql.GraphQLNonNull): graphql_type = graphql_type.of_type return graphql.GraphQLArgument(type_=graphql_type) graphql_query_type = to_graphql_type(query_type).of_type if mutation_type is None: graphql_mutation_type = None else: graphql_mutation_type = to_graphql_type(mutation_type).of_type for extra_type in types: to_graphql_type(extra_type) return Schema( query_type=query_type, mutation_type=mutation_type, types=types, graphql_schema=graphql.GraphQLSchema( query=graphql_query_type, mutation=graphql_mutation_type, types=tuple(graphql_types.values()), ), )
def graphql_schema(self): return graphql.GraphQLSchema( query=self.mapper.map(self.query, default_non_null=False), mutation=self.mapper.map(self.mutation, default_non_null=False))
schema = graphql.GraphQLSchema( query=graphql.GraphQLObjectType( name="RootQueryType", fields={ "name": graphql.GraphQLField( graphql.GraphQLString, resolve=resolve_name, args={ "title": graphql.GraphQLArgument( graphql.GraphQLNonNull(graphql.GraphQLString) ) }, ) }, ), subscription=graphql.GraphQLObjectType( name="RootSubscriptionType", fields={ "counter": graphql.GraphQLField( graphql.GraphQLString, resolve=resolve_counter, subscribe=subscribe_counter, args={ "ceil": graphql.GraphQLArgument( graphql.GraphQLNonNull(graphql.GraphQLInt) ) }, ) }, ), )
return g.ObjectType(name='Mutation', fields=mutations) # For extra types only which are unreachable from query and mutation types, # e.g. for WagtailPage interface implementations. def load_types(): types = [] for schema_module in get_schema_modules(): if not hasattr(schema_module, 'exported_types'): continue if not isinstance(schema_module.exported_types, list): raise Exception(f"Expected list for {schema_module}.exported_types") types.extend(schema_module.exported_types) return types def load_subscriptions(): subscriptions = object_from_modules('subscriptions') return g.ObjectType(name='Subscription', fields=subscriptions) schema = graphql.GraphQLSchema( query=load_queries(), mutation=load_mutations(), subscription=load_subscriptions(), types=load_types(), )
def graphql_schema( *, query: Iterable[Callable] = (), mutation: Iterable[Callable] = (), subscription: Iterable[Union[Subscribe, Tuple[Subscribe, Callable]]] = (), types: Iterable[Type] = (), aliaser: Aliaser = to_camel_case, id_types: Union[Collection[AnyType], IdPredicate] = None, error_as_null: bool = True, generic_ref_factory: GenericRefFactory = None, union_ref_factory: UnionRefFactory = None, directives: Optional[Collection[graphql.GraphQLDirective]] = None, description: Optional[str] = None, extensions: Optional[Dict[str, Any]] = None, ) -> graphql.GraphQLSchema: def operation_resolver(operation: Callable, *, skip_first=False) -> Resolver: if skip_first: wrapper = operation else: def wrapper(_, *args, **kwargs): return operation(*args, **kwargs) parameters = resolver_parameters(operation, skip_first=skip_first) return Resolver(operation, wrapper, parameters) query_fields: List[ObjectField] = [] mutation_fields: List[ObjectField] = [] subscription_fields: List[ObjectField] = [] for operations, fields in [(query, query_fields), (mutation, mutation_fields)]: for operation in operations: resolver = operation_resolver(operation) fields.append( ObjectField( operation.__name__, wrap_return_type(resolver.return_type, error_as_null), resolve=resolver_resolve(resolver, aliaser, error_as_null), parameters=field_parameters(resolver), schema=get_schema(operation), )) for operation in subscription: # type: ignore resolve: Callable if isinstance(operation, tuple): operation, event_handler = operation name, schema = event_handler.__name__, get_schema(event_handler) try: resolver = operation_resolver(event_handler, skip_first=True) except MissingFirstParameter: raise TypeError( "Subscription resolver must have at least one parameter" ) from None return_type = resolver.return_type subscribe = resolver_resolve( operation_resolver(operation), aliaser, error_as_null, serialized=False, ) resolve = resolver_resolve(resolver, aliaser, error_as_null) else: name, schema = operation.__name__, get_schema(operation) resolver = operation_resolver(operation) if get_origin(resolver.return_type) not in async_iterable_origins: raise TypeError( "Subscriptions must return an AsyncIterable/AsyncIterator") return_type = get_args(resolver.return_type)[0] subscribe = resolver_resolve(resolver, aliaser, error_as_null, serialized=False) def resolve(_, *args, **kwargs): return _ subscription_fields.append( ObjectField( name, wrap_return_type(return_type, error_as_null), parameters=field_parameters(resolver), resolve=resolve, subscribe=subscribe, schema=schema, )) is_id = id_types.__contains__ if isinstance(id_types, Collection) else id_types builder = OutputSchemaBuilder(aliaser, is_id, error_as_null, generic_ref_factory, union_ref_factory) def root_type( name: str, fields: Collection[ObjectField] ) -> Optional[graphql.GraphQLObjectType]: if not fields: return None return exec_thunk(builder.object(type(name, (), {}), fields), non_null=False) return graphql.GraphQLSchema( root_type("Query", query_fields), root_type("Mutation", mutation_fields), root_type("Subscription", subscription_fields), [exec_thunk(builder.visit(cls), non_null=False) for cls in types], directives, description, extensions, )