def build_connection_interface(self): if "INode" not in self.interfaces: self.interfaces["INode"] = GraphQLInterfaceType( "INode", self.query_fields(INode), description=self.type_description(INode), ) if "IEdge" not in self.interfaces: self.interfaces["IEdge"] = GraphQLInterfaceType( "IEdge", self.query_fields(IEdge), description=self.type_description(IEdge), ) if "IPageInfo" not in self.interfaces: self.interfaces["IPageInfo"] = GraphQLInterfaceType( "IPageInfo", self.query_fields(IPageInfo), description=self.type_description(IPageInfo), ) if "IConnection" not in self.interfaces: self.interfaces["IConnection"] = GraphQLInterfaceType( "IConnection", self.query_fields(IConnection), description=self.type_description(IConnection), )
def test_can_implement_graphql_core_interfaces(): HasName = GraphQLInterfaceType("HasName", fields={ "name": GraphQLField(GraphQLString), }, resolve_type=lambda: None) AuthorRecord = attr.make_class("AuthorRecord", ["name"]) class Author(StaticDataObjectType): __interfaces__ = [HasName] __records__ = [AuthorRecord("PG Wodehouse")] name = field(type=String) class Root(RootType): author = single(lambda: StaticDataObjectType.select(Author)) result = executor(Root)("""{ author { ...on HasName { name } } }""") assert_that( result, is_successful_result(data={ "author": { "name": "PG Wodehouse" }, }))
def graphql_type(cls): return GraphQLInterfaceType( name=getattr(cls, "name", cls.__name__.lower()), description=getattr(cls, "description", cls.__doc__), resolve_type=cls.resolve_type, fields=cls.graphql_fields, )
def from_interface(self, interface: TypeDefinition) -> GraphQLInterfaceType: # TODO: Use StrawberryInterface when it's implemented in another PR interface_name = self.config.name_converter.from_type(interface) # Don't reevaluate known types if interface_name in self.type_map: graphql_interface = self.type_map[interface_name].implementation assert isinstance(graphql_interface, GraphQLInterfaceType) # For mypy return graphql_interface def get_graphql_fields() -> Dict[str, GraphQLField]: graphql_fields = {} for field in interface.fields: field_name = self.config.name_converter.from_field(field) graphql_fields[field_name] = self.from_field(field) return graphql_fields graphql_interface = GraphQLInterfaceType( name=interface_name, fields=get_graphql_fields, interfaces=list(map(self.from_interface, interface.interfaces)), description=interface.description, ) self.type_map[interface_name] = ConcreteType( definition=interface, implementation=graphql_interface) return graphql_interface
def compile_interface(self, obj: Interface) -> GraphQLInterfaceType: assert isinstance(obj, Interface) compiled_type = GraphQLInterfaceType( # Object names are in CamelCase both in Python and GraphQL, # so no need for conversion here. name=obj.name, fields={}, # placeholder # TODO: do we need to wrap this, so we can convert types # on the fly? resolve_type=obj.resolve_type, description=obj.description, ) self.add_to_cache(obj, compiled_type) compiled_type.fields = { _name_to_graphql(name): self.compile_field(field) for name, field in obj.fields.items() } return compiled_type
def node_definitions( fetch_by_id: Callable[[str, GraphQLResolveInfo], Any], type_resolver: Optional[GraphQLTypeResolver] = None, ) -> GraphQLNodeDefinitions: """ Given a function to map from an ID to an underlying object, and a function to map from an underlying object to the concrete GraphQLObjectType it corresponds to, constructs a `Node` interface that objects can implement, and a field object to be used as a `node` root field. If the type_resolver is omitted, object resolution on the interface will be handled with the `is_type_of` method on object types, as with any GraphQL interface without a provided `resolve_type` method. """ node_interface = GraphQLInterfaceType( "Node", description="An object with an ID", fields=lambda: { "id": GraphQLField(GraphQLNonNull(GraphQLID), description="The id of the object.") }, resolve_type=type_resolver, ) # noinspection PyShadowingBuiltins node_field = GraphQLField( node_interface, description="Fetches an object given its ID", args={ "id": GraphQLArgument(GraphQLNonNull(GraphQLID), description="The ID of an object") }, resolve=lambda _obj, info, id: fetch_by_id(id, info), ) nodes_field = GraphQLField( GraphQLNonNull(GraphQLList(node_interface)), description="Fetches objects given their IDs", args={ "ids": GraphQLArgument( GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLID))), description="The IDs of objects", ) }, resolve=lambda _obj, info, ids: [fetch_by_id(id_, info) for id_ in ids], ) return GraphQLNodeDefinitions(node_interface, node_field, nodes_field)
def from_interface(self, interface: TypeDefinition) -> GraphQLInterfaceType: # TODO: Use StrawberryInterface when it's implemented in another PR # Don't reevaluate known types if interface.name in self.type_map: graphql_interface = self.type_map[interface.name].implementation assert isinstance(graphql_interface, GraphQLInterfaceType) # For mypy return graphql_interface def get_graphql_fields() -> Dict[str, GraphQLField]: graphql_fields = {} for field in interface.fields: field_name = field.get_graphql_name( self.config.auto_camel_case) graphql_fields[field_name] = self.from_field(field) return graphql_fields def resolve_type( obj: Any, info: GraphQLResolveInfo, type_: Union[GraphQLInterfaceType, GraphQLUnionType], ) -> GraphQLObjectType: # TODO: this will probably break when passing dicts # or even non strawberry types resolved_type = self.type_map[ obj.__class__._type_definition.name].implementation assert isinstance(resolved_type, GraphQLObjectType) return resolved_type graphql_interface = GraphQLInterfaceType( name=interface.name, fields=get_graphql_fields, interfaces=list(map(self.from_interface, interface.interfaces)), description=interface.description, resolve_type=resolve_type, ) self.type_map[interface.name] = ConcreteType( definition=interface, implementation=graphql_interface) return graphql_interface
def __new__(meta, name, bases, attrs): cls = super(InterfaceTypeMeta, meta).__new__(meta, name, bases, attrs) if attrs.get("__abstract__"): return cls def fields(): fields = _declare_fields(cls)() return dict((key, field.to_graphql_field()) for key, field in six.iteritems(fields)) cls.__graphql__ = GraphQLInterfaceType( name=cls.__name__, fields=fields, resolve_type=lambda: None, ) return cls
def _define_types(self): abstract_types = [] obj_types = [] for modname in self.modules: # get all descendants of this abstract type module = self.edb_schema.get_module(modname) abstract_types += [ t for t in module.get_objects() if isinstance(t, ObjectType) and t.is_abstract ] obj_types += [ t for t in module.get_objects() if isinstance(t, ObjectType) and not t.is_abstract ] # interfaces for t in abstract_types: gqltype = GraphQLInterfaceType( name=self.get_short_name(t.name), fields=partial(self.get_fields, t.name), resolve_type=lambda obj, info: obj, ) self._gql_interfaces[t.name] = gqltype # object types for t in obj_types: interfaces = [] # views are currently skipped if t.is_view(): continue for st in t.get_mro(): if (isinstance(st, ObjectType) and st.is_abstract and st.name in self._gql_interfaces): interfaces.append(self._gql_interfaces[st.name]) gqltype = GraphQLObjectType( name=self.get_short_name(t.name), fields=partial(self.get_fields, t.name), interfaces=interfaces, ) self._gql_objtypes[t.name] = gqltype
def _define_types(self): interface_types = [] obj_types = [] self.define_enums() self.define_generic_filter_types() self.define_generic_order_types() self.define_generic_insert_types() # Every ObjectType is reflected as an interface. interface_types = list( self.edb_schema.get_objects(included_modules=self.modules, type=s_objtypes.ObjectType)) # concrete types are also reflected as Type (with a '_Type' postfix) obj_types += [ t for t in interface_types if not t.get_is_abstract(self.edb_schema) ] # interfaces for t in interface_types: t_name = t.get_name(self.edb_schema) gql_name = self.get_gql_name(t_name) gqltype = GraphQLInterfaceType( name=gql_name, fields=partial(self.get_fields, t_name), resolve_type=lambda obj, info: obj, description=self._get_description(t), ) self._gql_interfaces[t_name] = gqltype # input object types corresponding to this interface gqlfiltertype = GraphQLInputObjectType( name=self.get_input_name('Filter', gql_name), fields=partial(self.get_filter_fields, t_name), ) self._gql_inobjtypes[t_name] = gqlfiltertype # ordering input type gqlordertype = GraphQLInputObjectType( name=self.get_input_name('Order', gql_name), fields=partial(self.get_order_fields, t_name), ) self._gql_ordertypes[t_name] = gqlordertype # update object types corresponding to this object (all # non-views can appear as update types) if not t.is_view(self.edb_schema): # only objects that have at least one non-readonly # link/property are eligible pointers = t.get_pointers(self.edb_schema) if any(not p.get_readonly(self.edb_schema) for _, p in pointers.items(self.edb_schema)): gqlupdatetype = GraphQLInputObjectType( name=self.get_input_name('Update', gql_name), fields=partial(self.get_update_fields, t_name), ) self._gql_inobjtypes[f'Update{t_name}'] = gqlupdatetype # object types for t in obj_types: interfaces = [] t_name = t.get_name(self.edb_schema) if t_name in self._gql_interfaces: interfaces.append(self._gql_interfaces[t_name]) ancestors = t.get_ancestors(self.edb_schema) for st in ancestors.objects(self.edb_schema): if (st.is_object_type() and st.get_name(self.edb_schema) in self._gql_interfaces): interfaces.append(self._gql_interfaces[st.get_name( self.edb_schema)]) gql_name = self.get_gql_name(t_name) gqltype = GraphQLObjectType( name=gql_name + '_Type', fields=partial(self.get_fields, t_name), interfaces=interfaces, description=self._get_description(t), ) self._gql_objtypes[t_name] = gqltype # input object types corresponding to this object (only # real objects can appear as input objects) if not t.is_view(self.edb_schema): gqlinserttype = GraphQLInputObjectType( name=self.get_input_name('Insert', gql_name), fields=partial(self.get_insert_fields, t_name), ) self._gql_inobjtypes[f'Insert{t_name}'] = gqlinserttype
def _define_types(self): interface_types = [] obj_types = [] self.define_enums() self.define_generic_filter_types() self.define_generic_order_types() # Every ObjectType is reflected as an interface. interface_types = list( self.edb_schema.get_objects(modules=self.modules, type=s_objtypes.BaseObjectType)) # concrete types are also reflected as Type (with a 'Type' postfix) obj_types += [t for t in interface_types if not t.get_is_abstract(self.edb_schema)] # interfaces for t in interface_types: t_name = t.get_name(self.edb_schema) gql_name = self.get_gql_name(t_name) gqltype = GraphQLInterfaceType( name=gql_name, fields=partial(self.get_fields, t_name), resolve_type=lambda obj, info: obj, ) self._gql_interfaces[t_name] = gqltype # input object types corresponding to this interface gqlfiltertype = GraphQLInputObjectType( name=self.get_input_name('Filter', gql_name), fields=partial(self.get_filter_fields, t_name), ) self._gql_inobjtypes[t_name] = gqlfiltertype # ordering input type gqlordertype = GraphQLInputObjectType( name=self.get_input_name('Order', gql_name), fields=partial(self.get_order_fields, t_name), ) self._gql_ordertypes[t_name] = gqlordertype # object types for t in obj_types: interfaces = [] t_name = t.get_name(self.edb_schema) if t_name in self._gql_interfaces: interfaces.append(self._gql_interfaces[t_name]) ancestors = t.get_ancestors(self.edb_schema) for st in ancestors.objects(self.edb_schema): if (isinstance(st, s_objtypes.ObjectType) and st.get_name(self.edb_schema) in self._gql_interfaces): interfaces.append( self._gql_interfaces[st.get_name(self.edb_schema)]) gql_name = self.get_gql_name(t_name) gqltype = GraphQLObjectType( name=gql_name + 'Type', fields=partial(self.get_fields, t_name), interfaces=interfaces, ) self._gql_objtypes[t_name] = gqltype
}, description="One of the films in the Star Wars Trilogy", ) character_interface = GraphQLInterfaceType( "Character", lambda: { "id": GraphQLField( GraphQLNonNull(GraphQLString), description="The id of the character." ), "name": GraphQLField(GraphQLString, description="The name of the character."), "friends": GraphQLField( GraphQLList(character_interface), description="The friends of the character," " or an empty list if they have none.", ), "appearsIn": GraphQLField( GraphQLList(episode_enum), description="Which movies they appear in." ), "secretBackstory": GraphQLField( GraphQLString, description="All secrets about their past." ), }, resolve_type=get_character_type, description="A character in the Star Wars Trilogy", ) human_type = GraphQLObjectType( "Human", lambda: { "id": GraphQLField(
def _define_types(self): interface_types = [] obj_types = [] self.define_generic_filter_types() self.define_generic_order_types() for modname in self.modules: # get all descendants of this abstract type module = self.edb_schema.get_module(modname) # every ObjectType is reflected as an interface interface_types += [t for t in module.get_objects() if isinstance(t, ObjectType)] # concrete types are also reflected as Type (with a 'Type' postfix) obj_types += [t for t in interface_types if not t.is_abstract] # interfaces for t in interface_types: short_name = self.get_short_name(t.name) gqltype = GraphQLInterfaceType( name=short_name, fields=partial(self.get_fields, t.name), resolve_type=lambda obj, info: obj, ) self._gql_interfaces[t.name] = gqltype # input object types corresponding to this interface gqlfiltertype = GraphQLInputObjectType( name='Filter' + short_name, fields=partial(self.get_filter_fields, t.name), ) self._gql_inobjtypes[t.name] = gqlfiltertype # ordering input type gqlordertype = GraphQLInputObjectType( name='Order' + short_name, fields=partial(self.get_order_fields, t.name), ) self._gql_ordertypes[t.name] = gqlordertype # object types for t in obj_types: interfaces = [] # views are currently skipped if t.is_view(): continue for st in t.get_mro(): if (isinstance(st, ObjectType) and st.name in self._gql_interfaces): interfaces.append(self._gql_interfaces[st.name]) short_name = self.get_short_name(t.name) gqltype = GraphQLObjectType( name=short_name + 'Type', fields=partial(self.get_fields, t.name), interfaces=interfaces, ) self._gql_objtypes[t.name] = gqltype
def resolve_node_type(obj, info): # See also: https://stackoverflow.com/q/34726666/196206 if obj.node_type == 'Post': return Post if obj.node_type == 'Category': return Category if obj.node_type == 'Topic': return Topic if obj.node_type == 'Conversation': return Conversation raise Exception(f'Unknown node type: {obj!r}') NodeInterface = GraphQLInterfaceType( name='Node', fields={ 'id': GraphQLField(type=GraphQLNonNull(GraphQLID)), }, resolve_type=resolve_node_type) ReplyPost = GraphQLObjectType( name='ReplyPost', interfaces=[NodeInterface], fields=lambda: { 'id': GraphQLField(type=GraphQLNonNull(GraphQLID)), 'bodyMarkdown': GraphQLField(type=GraphQLString, resolver=lambda post, info: post.body_markdown), }) ReplyPostConnection = relay_connection_type(ReplyPost)
'JEDI': GraphQLEnumValue(6, description='Released in 1983.') }, description='One of the films in the Star Wars Trilogy') character_interface = GraphQLInterfaceType( 'Character', lambda: { 'id': GraphQLField(GraphQLNonNull(GraphQLString), description='The id of the character.'), 'name': GraphQLField(GraphQLString, description='The name of the character.'), 'friends': GraphQLField(GraphQLList(character_interface), description='The friends of the character,' ' or an empty list if they have none.'), 'appearsIn': GraphQLField(GraphQLList(episode_enum), description='Which movies they appear in.'), 'secretBackstory': GraphQLField(GraphQLString, description='All secrets about their past.') }, resolve_type=lambda character, _info: { 'Human': human_type, 'Droid': droid_type }.get(character.type), description='A character in the Star Wars Trilogy') human_type = GraphQLObjectType( 'Human', lambda: {
def map_interface(self, cls: Type[Interface]) -> GraphQLInterfaceType: return GraphQLInterfaceType( name=cls.__name__, description=cls.__doc__, fields=lambda: self.map_fields(cls), )
human_type: GraphQLObjectType droid_type: GraphQLObjectType character_interface = GraphQLInterfaceType( "Character", lambda: { "id": GraphQLField( GraphQLNonNull(GraphQLString), description="The id of the character." ), "name": GraphQLField(GraphQLString, description="The name of the character."), "friends": GraphQLField( GraphQLList(character_interface), # type: ignore description="The friends of the character," " or an empty list if they have none.", ), "appearsIn": GraphQLField( GraphQLList(episode_enum), description="Which movies they appear in." ), }, resolve_type=lambda character, _info, _type: { "Human": human_type.name, "Droid": droid_type.name, }[character.type], description="A character in the Star Wars Trilogy", ) human_type = GraphQLObjectType( "Human", lambda: { "id": GraphQLField(
description="Released in 1983.", ), }, ) characterInterface = GraphQLInterfaceType( "Character", description="A character in the Star Wars Trilogy", fields=lambda: { "id": GraphQLField(GraphQLNonNull(GraphQLString), description="The id of the character."), "name": GraphQLField(GraphQLString, description="The name of the character."), "friends": GraphQLField( GraphQLList(characterInterface), # type: ignore description="The friends of the character," " or an empty list if they have none.", ), "appearsIn": GraphQLField(GraphQLList(episodeEnum), description="Which movies they appear in."), }, resolve_type=lambda character, *_: humanType # type: ignore if getHuman(character.id) else droidType, # type: ignore ) humanType = GraphQLObjectType( "Human", description="A humanoid creature in the Star Wars universe.", fields=lambda: {
type=GraphQLInt, description='DNS query name risk score value. 1->High, 2->Medium, 3->Low', resolver=lambda root, *_: root.get('dns_sev') or 0 ), 'clientIpScore': GraphQLField( type=GraphQLInt, description='Client IP address risk score value. 1->High, 2->Medium, 3->Low', resolver=lambda root, *_: root.get('ip_sev') or 0 ) } ) CommentInterface = GraphQLInterfaceType( name='DnsCommentInterface', fields={ 'title': GraphQLField(GraphQLString), 'text': GraphQLField(GraphQLString) }, resolve_type=lambda root, *_: QueryCommentType if root.get('dns_threat') else ClientIpCommentType ) QueryCommentType = GraphQLObjectType( name='DnsQueryCommentType', interfaces=[CommentInterface], fields={ 'dnsQuery': GraphQLField( type=GraphQLString, description='High risk DNS query name', resolver=lambda root, *_: root.get('dns_threat') ), 'title': GraphQLField( type=GraphQLString,