Exemple #1
0
 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),
         )
Exemple #2
0
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"
            },
        }))
Exemple #3
0
 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
Exemple #5
0
    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
Exemple #6
0
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)
Exemple #7
0
    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
Exemple #8
0
    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
Exemple #9
0
    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
Exemple #10
0
    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
Exemple #11
0
    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
Exemple #12
0
    },
    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(
Exemple #13
0
    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
Exemple #14
0
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)
Exemple #15
0
        '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: {
Exemple #16
0
 def map_interface(self, cls: Type[Interface]) -> GraphQLInterfaceType:
     return GraphQLInterfaceType(
         name=cls.__name__,
         description=cls.__doc__,
         fields=lambda: self.map_fields(cls),
     )
Exemple #17
0

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(
Exemple #18
0
            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: {
Exemple #19
0
            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,