def test_field_args_is_union_of_original_field_args(self): self._assert_merge( [ GraphQLObjectType("Object", fields={ "id": GraphQLField( type=GraphQLInt, args={"id": GraphQLArgument(type=GraphQLInt)}, ), }), GraphQLObjectType("Object", fields={ "id": GraphQLField( type=GraphQLInt, args={ "id": GraphQLArgument(type=GraphQLInt), "name": GraphQLArgument(type=GraphQLString), }, ), }), ], is_object_type(fields=has_entries({ "id": is_field(args=has_entries({ "id": is_arg(type=is_int), "name": is_arg(type=is_string), })), })), )
def build_schema(base: DeclarativeMeta, enable_subscription: bool = False) -> GraphQLSchema: """ Args: base: enable_subscription: Returns: :class:`graphql:graphql.type.GraphQLSchema` """ queries: GraphQLFieldMap = {} mutations: GraphQLFieldMap = {} objects: Objects = {} inputs: Inputs = {} for model in base.__subclasses__(): build_queries(model, objects, queries, inputs) build_mutations(model, objects, mutations, inputs) return GraphQLSchema( GraphQLObjectType("Query", queries), GraphQLObjectType("Mutation", mutations), GraphQLObjectType("Subscription", {}) if enable_subscription else None, )
def test_non_nullable_list(self): PersonType = GraphQLObjectType( "Person", lambda: {"name": GraphQLField(GraphQLString)} ) schema = GraphQLSchema( query=GraphQLObjectType( name="RootQueryType", fields={ "people": GraphQLField( GraphQLList(GraphQLNonNull(PersonType)), resolve=lambda obj, info: {"name": "eran"}, ) }, ) ) query = """ query GetPeople { people { name } } """ parser = QueryParser(schema) dataclass_renderer = DataclassesRenderer(schema) parsed = parser.parse(query) rendered = dataclass_renderer.render(parsed) m = self.load_module(rendered) mock_client = MagicMock() mock_client.call = MagicMock( return_value=""" { "data": { "people": [ { "name": "eran" }, { "name": "eran1" } ] } } """ ) result = m.GetPeople.execute(mock_client) assert result assert isinstance(result, m.GetPeople.GetPeopleData) assert len(result.people) == 2 assert result.people[0].name == "eran" assert result.people[1].name == "eran1"
def generate_schema(self) -> GraphQLSchema: """ Finalizes the GraphQL schema by generating the GraphQLSchema :return: The finalized GraphQL schema """ query = GraphQLObjectType("Query", self.gql_queries) mutation = GraphQLObjectType("Mutation", self.gql_mutations) return GraphQLSchema(query, mutation)
def test_batches_correctly(executor): Business = GraphQLObjectType( 'Business', lambda: { 'id': GraphQLField(GraphQLID, resolver=lambda root, info, **args: root), }) Query = GraphQLObjectType( 'Query', lambda: { 'getBusiness': GraphQLField(Business, args={ 'id': GraphQLArgument(GraphQLNonNull(GraphQLID)), }, resolver=lambda root, info, **args: info.context. business_data_loader.load(args.get('id'))), }) schema = GraphQLSchema(query=Query) doc = ''' { business1: getBusiness(id: "1") { id } business2: getBusiness(id: "2") { id } } ''' doc_ast = parse(doc) load_calls = [] class BusinessDataLoader(DataLoader): def batch_load_fn(self, keys): load_calls.append(keys) return Promise.resolve(keys) class Context(object): business_data_loader = BusinessDataLoader() result = execute(schema, doc_ast, None, context_value=Context(), executor=executor) assert not result.errors assert result.data == { 'business1': { 'id': '1' }, 'business2': { 'id': '2' }, } assert load_calls == [['1', '2']]
def test_batches_correctly(executor): # type: (SyncExecutor) -> None Business = GraphQLObjectType( "Business", lambda: { "id": GraphQLField(GraphQLID, resolver=lambda root, info, **args: root) }, ) Query = GraphQLObjectType( "Query", lambda: { "getBusiness": GraphQLField( Business, args={"id": GraphQLArgument(GraphQLNonNull(GraphQLID))}, resolver=lambda root, info, **args: info.context. business_data_loader.load(args.get("id")), ) }, ) schema = GraphQLSchema(query=Query) doc = """ { business1: getBusiness(id: "1") { id } business2: getBusiness(id: "2") { id } } """ doc_ast = parse(doc) load_calls = [] class BusinessDataLoader(DataLoader): def batch_load_fn(self, keys): # type: (List[str]) -> Promise load_calls.append(keys) return Promise.resolve(keys) class Context(object): business_data_loader = BusinessDataLoader() result = execute(schema, doc_ast, None, context_value=Context(), executor=executor) assert not result.errors assert result.data == {"business1": {"id": "1"}, "business2": {"id": "2"}} assert load_calls == [["1", "2"]]
def test_can_handle_recursive_types(self): obj_1 = GraphQLObjectType("Object", fields=lambda: {"self": GraphQLField(type=obj_1)}) obj_2 = GraphQLObjectType("Object", fields=lambda: {"self": GraphQLField(type=obj_2)}) assert is_subtype(obj_1, obj_2) obj_1 = GraphQLObjectType("Object", fields=lambda: {"self": GraphQLField(type=obj_1)}) obj_2 = GraphQLObjectType("Object", fields=lambda: {"self": GraphQLField(type=GraphQLNonNull(obj_2))}) assert not is_subtype(obj_1, obj_2)
def test_merged_object_type_has_name_of_original_type(self): self._assert_merge( [ GraphQLObjectType("Object", fields={ "id": GraphQLField(type=GraphQLInt), }), GraphQLObjectType("Object", fields={ "id": GraphQLField(type=GraphQLInt), }), ], has_properties(name="Object"), )
def add_resolve_functions_to_scalar(name: str, obj: GraphQLObjectType, resolvers: dict): scalar_resolvers = resolvers.get(name, {}) serialize = scalar_resolvers.get("serialize", obj.serialize) obj.serialize = serialize parse_literal = scalar_resolvers.get("parse_literal", obj.parse_literal) obj.parse_literal = parse_literal parse_value = scalar_resolvers.get("parse_value", obj.parse_value) obj.parse_value = parse_value
def __init__(self, edb_schema): '''Create a graphql schema based on edgedb schema.''' self.edb_schema = edb_schema # extract and sort modules to have a consistent type ordering self.modules = { m.get_name(self.edb_schema) for m in self.edb_schema.get_objects(type=s_mod.Module) } - HIDDEN_MODULES self.modules = list(self.modules) self.modules.sort() self._gql_interfaces = {} self._gql_objtypes = {} self._gql_inobjtypes = {} self._gql_ordertypes = {} self._gql_enums = {} self._define_types() query = self._gql_objtypes['Query'] = GraphQLObjectType( name='Query', fields=self.get_fields('Query'), ) # If a database only has abstract types and scalars, no # mutations will be possible (such as in a blank database), # but we would still want the reflection to work without # error, even if all that can be discovered through GraphQL # then is the schema. fields = self.get_fields('Mutation') if fields: mutation = self._gql_objtypes['Mutation'] = GraphQLObjectType( name='Mutation', fields=fields, ) else: mutation = None # get a sorted list of types relevant for the Schema types = [ objt for name, objt in itertools.chain( self._gql_objtypes.items(), self._gql_inobjtypes.items()) # the Query is included separately if name not in TOP_LEVEL_TYPES ] types = sorted(types, key=lambda x: x.name) self._gql_schema = GraphQLSchema(query=query, mutation=mutation, types=types) # this map is used for GQL -> EQL translator needs self._type_map = {}
def connection_definitions( node_type: Union[GraphQLNamedOutputType, GraphQLNonNull[GraphQLNamedOutputType]], name: Optional[str] = None, resolve_node: Optional[GraphQLFieldResolver] = None, resolve_cursor: Optional[GraphQLFieldResolver] = None, edge_fields: Optional[Thunk[GraphQLFieldMap]] = None, connection_fields: Optional[Thunk[GraphQLFieldMap]] = None, ) -> GraphQLConnectionDefinitions: """Return GraphQLObjectTypes for a connection with the given name. The nodes of the returned object types will be of the specified type. """ name = name or get_named_type(node_type).name edge_type = GraphQLObjectType( name + "Edge", description="An edge in a connection.", fields=lambda: { "node": GraphQLField( node_type, resolve=resolve_node, description="The item at the end of the edge", ), "cursor": GraphQLField( GraphQLNonNull(GraphQLString), resolve=resolve_cursor, description="A cursor for use in pagination", ), **resolve_maybe_thunk(edge_fields or {}), }, ) connection_type = GraphQLObjectType( name + "Connection", description="A connection to a list of items.", fields=lambda: { "pageInfo": GraphQLField( GraphQLNonNull(page_info_type), description="Information to aid in pagination.", ), "edges": GraphQLField(GraphQLList(edge_type), description="A list of edges."), **resolve_maybe_thunk(connection_fields or {}), }, ) return GraphQLConnectionDefinitions(edge_type, connection_type)
def test_field_type_is_common_subtype_of_field_types(self): self._assert_merge( [ GraphQLObjectType("Object", fields={ "id": GraphQLField(type=GraphQLNonNull(GraphQLInt)), }), GraphQLObjectType("Object", fields={ "id": GraphQLField(type=GraphQLInt), }), ], is_object_type(fields=has_entries({ "id": is_field(type=is_non_null(is_int)), })), )
def test_when_query_is_not_subtype_then_schema_is_not_subtype(self): assert not is_subtype( GraphQLSchema( query=GraphQLObjectType("Object", fields={ "id": GraphQLField(type=GraphQLInt), }), ), GraphQLSchema( query=GraphQLObjectType("Object", fields={ "id": GraphQLField(type=GraphQLInt), "name": GraphQLField(type=GraphQLString), }), ), )
def test_types_within_list_types_are_merged(self): self._assert_merge( [ GraphQLList(GraphQLObjectType("Object", fields={ "id": GraphQLField(type=GraphQLInt), })), GraphQLList(GraphQLObjectType("Object", fields={ "name": GraphQLField(type=GraphQLString), })), ], is_list_type(is_object_type(fields=has_entries({ "id": is_field(type=is_int), "name": is_field(type=is_string), }))), )
def relay_connection_type(node_type): base_name = node_type.name Edge = GraphQLObjectType( name=base_name + 'Edge', fields={ 'cursor': GraphQLField(type=GraphQLNonNull(GraphQLString)), 'node': GraphQLField(type=node_type), }) Connection = GraphQLObjectType( name=base_name + 'Connection', fields={ 'pageInfo': GraphQLField(type=GraphQLNonNull(PageInfoType)), 'edges': GraphQLField(type=GraphQLList(Edge)), }) return Connection
def test_object_types_are_merged_to_object_type_with_union_of_fields(self): self._assert_merge( [ GraphQLObjectType("Object", fields={ "id": GraphQLField(type=GraphQLInt), }), GraphQLObjectType("Object", fields={ "name": GraphQLField(type=GraphQLString), }), ], is_object_type(fields=has_entries({ "id": is_field(type=is_int), "name": is_field(type=is_string), })), )
def test_when_field_has_extra_non_null_args_then_is_not_subtype(self): assert not is_subtype( GraphQLObjectType("Object", { "value": GraphQLField( type=GraphQLNonNull(GraphQLInt), args={"id": GraphQLArgument(type=GraphQLNonNull(GraphQLInt))}, ) }), GraphQLObjectType("Object", { "value": GraphQLField( type=GraphQLNonNull(GraphQLInt), args={}, ) }), )
def test_when_field_has_arg_of_supertype_then_is_subtype(self): assert is_subtype( GraphQLObjectType("Object", { "value": GraphQLField( type=GraphQLNonNull(GraphQLInt), args={"id": GraphQLArgument(type=GraphQLInt)}, ) }), GraphQLObjectType("Object", { "value": GraphQLField( type=GraphQLNonNull(GraphQLInt), args={"id": GraphQLArgument(type=GraphQLNonNull(GraphQLInt))}, ) }), )
def test_when_arg_is_missing_then_is_not_subtype(self): assert not is_subtype( GraphQLObjectType("Object", { "value": GraphQLField( type=GraphQLNonNull(GraphQLInt), args={}, ) }), GraphQLObjectType("Object", { "value": GraphQLField( type=GraphQLNonNull(GraphQLInt), args={"id": GraphQLArgument(type=GraphQLInt)}, ) }), )
def __init__(self): super().__init__() self.report_type = GraphQLObjectType( "Status", lambda: { "id": GraphQLField( GraphQLNonNull(GraphQLString), description="The id of the API instance.", ), "currentStatus": GraphQLField(GraphQLString, description="The API status."), "currentTime": GraphQLField(GraphQLString, description="The current API time."), }, ) self.q = { "Status": GraphQLField(self.report_type, resolve=self.get_report) } self.s = { "Status": GraphQLField(self.report_type, subscribe=self.sub_report, resolve=None) }
def build_object_type(model: DeclarativeMeta, objects: Objects) -> GraphQLObjectType: def get_column_field(column: Column) -> GraphQLOutputType: if column.nullable: return get_graphql_type_from_column(column.type) else: return GraphQLNonNull(get_graphql_type_from_column(column.type)) def get_relationship_field( relationship: RelationshipProperty) -> GraphQLOutputType: if relationship.direction in (interfaces.ONETOMANY, interfaces.MANYTOMANY): return GraphQLList(objects[get_table_name( relationship.mapper.entity)]) else: return objects[get_table_name(relationship.mapper.entity)] def get_fields() -> GraphQLFieldMap: fields = { **{ column.name: GraphQLField(get_column_field(column), resolve=make_field_resolver(column.name)) for column in get_table(model).columns }, **{ name: GraphQLField(get_relationship_field(relationship), resolve=make_field_resolver(name)) for name, relationship in get_relationships(model) }, } return fields return GraphQLObjectType(get_table_name(model), get_fields)
def _common_subtype(left, right): if left == right: return left elif isinstance(left, GraphQLNonNull) and isinstance( right, GraphQLNonNull): return GraphQLNonNull(_common_subtype(left.of_type, right.of_type)) elif isinstance(left, GraphQLNonNull): return GraphQLNonNull(_common_subtype(left.of_type, right)) elif isinstance(right, GraphQLNonNull): return GraphQLNonNull(_common_subtype(left, right.of_type)) elif isinstance(left, GraphQLList) and isinstance(right, GraphQLList): return GraphQLList(_common_subtype(left.of_type, right.of_type)) elif isinstance(left, GraphQLObjectType) and isinstance( right, GraphQLObjectType): fields = dict((field_name, _common_subfield(left.fields.get(field_name), right.fields.get(field_name))) for field_name in set(left.fields.keys()) | set(right.fields.keys())) return GraphQLObjectType(left.name, fields=fields) elif isinstance(left, GraphQLSchema) and isinstance(right, GraphQLSchema): return GraphQLSchema(query=_common_subtype(left.get_query_type(), right.get_query_type())) else: raise ValueError("Cannot find common subtype")
def create_type(): return GraphQLObjectType( name='TodoItem', fields=lambda: { 'text': GraphQLField(type=GraphQLString), }, )
def __init__(self): super().__init__(self) self.nav_sat_fix_data = {"uuid": "test"} self.nav_sat_fix_message_type = GraphQLObjectType( "NavSatFix", lambda: { "uuid": GraphQLField(GraphQLString, description="The uuid of the vehicle."), "seq": GraphQLField(GraphQLInt, description="The sequence number of the message." ), "secs": GraphQLField(GraphQLInt, description=""), "nsecs": GraphQLField(GraphQLInt, description=""), "frameId": GraphQLField(GraphQLString, description=""), "statusStatus": GraphQLField(GraphQLInt, description=""), "statusService": GraphQLField(GraphQLInt, description=""), "latitude": GraphQLField(GraphQLFloat, description=""), "longitude": GraphQLField(GraphQLFloat, description=""), "altitude": GraphQLField(GraphQLFloat, description=""), # TODO: position_covariance array "positionCovarianceType": GraphQLField(GraphQLInt, description=""), }, description="MAVROS NavSatFixMessage", ) self.q = { "NavSatFix": GraphQLField(self.nav_sat_fix_message_type, resolve=self.get_nav_sat_fix_message) } self.m = { "NavSatFix": GraphQLField( self.nav_sat_fix_message_type, args=self.get_mutation_args(self.nav_sat_fix_message_type), resolve=self.set_nav_sat_fix_message, ) } self.s = { "NavSatFix": GraphQLField( self.nav_sat_fix_message_type, subscribe=self.sub_nav_sat_fix_message, resolve=None, ) }
def build_object_type(model: DeclarativeMeta, objects: Objects) -> GraphQLObjectType: def get_fields() -> GraphQLFieldMap: fields = {} for column in get_table(model).columns: graphql_type: GraphQLOutputType = get_graphql_type_from_column( column.type) if not column.nullable: graphql_type = GraphQLNonNull(graphql_type) fields[column.name] = GraphQLField(graphql_type, resolve=make_field_resolver( column.name)) for name, relationship in get_relationships(model): object_type: GraphQLOutputType = objects[get_table_name( relationship.mapper.entity)] if relationship.direction in (interfaces.ONETOMANY, interfaces.MANYTOMANY): object_type = GraphQLList(object_type) fields[name] = GraphQLField(object_type, resolve=make_field_resolver(name)) return fields return GraphQLObjectType(get_table_name(model), get_fields)
def from_object(self, object_type: TypeDefinition) -> GraphQLObjectType: # TODO: Use StrawberryObjectType when it's implemented in another PR # Don't reevaluate known types if object_type.name in self.type_map: graphql_object_type = self.type_map[ object_type.name].implementation assert isinstance(graphql_object_type, GraphQLObjectType) # For mypy return graphql_object_type def get_graphql_fields() -> Dict[str, GraphQLField]: graphql_fields = {} for field in object_type.fields: field_name = field.get_graphql_name( self.config.auto_camel_case) graphql_fields[field_name] = self.from_field(field) return graphql_fields graphql_object_type = GraphQLObjectType( name=object_type.name, fields=get_graphql_fields, interfaces=list(map(self.from_interface, object_type.interfaces)), description=object_type.description, ) self.type_map[object_type.name] = ConcreteType( definition=object_type, implementation=graphql_object_type) return graphql_object_type
def __init__(self, edb_schema): '''Create a graphql schema based on edgedb schema.''' self.edb_schema = edb_schema # extract and sort modules to have a consistent type ordering self.modules = { m.name for m in self.edb_schema.get_modules() } - {'schema', 'graphql'} self.modules = list(self.modules) self.modules.sort() self._gql_interfaces = {} self._gql_objtypes = {} self._gql_inobjtypes = {} self._gql_ordertypes = {} self._define_types() query = self._gql_objtypes['Query'] = GraphQLObjectType( name='Query', fields=self.get_fields('Query'), ) # get a sorted list of types relevant for the Schema types = [ objt for name, objt in itertools.chain(self._gql_objtypes.items(), self._gql_inobjtypes.items()) # the Query is included separately if name != 'Query' ] types = sorted(types, key=lambda x: x.name) self._gql_schema = GraphQLSchema(query=query, types=types)
def create_type(): return GraphQLObjectType( name='WorksheetInstance', fields=lambda: { 'id': GraphQLField( type=req(GraphQLID), resolver=lambda obj, args, *_: obj.obj_id(*args), ), 'reportRecordNumber': GraphQLField( type=req(GraphQLInt), resolver=lambda obj, args, *_: obj.report_record_number( *args), ), 'worksheetCode': GraphQLField( type=req(GraphQLString), resolver=lambda obj, args, *_: obj.worksheet_code(*args), ), 'entries': GraphQLField(type=req( list_of(req(GraphQLWorksheetEntry.type())))), }, )
def test_accepts_type_definition_with_sync_subscribe_function(): # type: () -> None SubscriptionType = GraphQLObjectType( name="Subscription", fields=OrderedDict([( "importantEmail", GraphQLField(EmailEventType, resolver=lambda *_: Observable.from_([None])), )]), ) test_schema = GraphQLSchema(query=QueryType, subscription=SubscriptionType) stream = Subject() send_important_email, subscription = create_subscription( stream, test_schema) email = Email( from_="*****@*****.**", subject="Alright", message="Tests are good", unread=True, ) inbox = [] subscription.subscribe(inbox.append) send_important_email(email) assert len(inbox) == 1 assert inbox[0].data == {"importantEmail": None}
def test_accepts_multiple_subscription_fields_defined_in_schema(): # type: () -> None SubscriptionTypeMultiple = GraphQLObjectType( name="Subscription", fields=OrderedDict([ ("importantEmail", GraphQLField(EmailEventType)), ("nonImportantEmail", GraphQLField(EmailEventType)), ]), ) test_schema = GraphQLSchema(query=QueryType, subscription=SubscriptionTypeMultiple) stream = Subject() send_important_email, subscription = create_subscription( stream, test_schema) email = Email( from_="*****@*****.**", subject="Alright", message="Tests are good", unread=True, ) inbox = [] stream.subscribe(inbox.append) send_important_email(email) assert len(inbox) == 1 assert inbox[0][0] == email