Part2: Resolvers#

In order to use our graph we need to connect the schema to our code. When the graph is parsed the type objects do not have any implemention we need to tell graphql how to resolve it. The easiest way to do this is to set the root_value to a mapping of operation names to functions.

The functions we will add can be async functions that must accept at least one argment for the GraphQLResolveInfo. This holds the schema and query information along with the context that is generated for each request and is a place to read and write data to pass to other resolvers in the query. Typically this is just the request data like Authorization headers, but could be anything. In our example we will use cannula.ResolveInfo which is a subclass that adds some functionality we will use later.

The resolvers can return objects or dictionaries as long as they are the correct ‘shape’. For us that means there should be id, name, and email:

For organization we’ll move the GraphQL application and resolvers into a separate module graph.py:

import pathlib
import cannula

from dashboard.core.config import config

async def resolve_me(info: cannula.ResolveInfo):
    return {
        "name": "Tiny Tim",
        "email": "tim@example.com",
        "id": "1",
    }

cannula_app = cannula.API(
    schema=pathlib.Path(config.root / "part1"),
    root_value={"me": resolve_me},
)

The root route and template remain the same except for moving the graphql application. You can view the results: http://localhost:8000/part2/ and see that we get an error now:

errors=[
    GraphQLError(
        "Abstract type 'Persona' must resolve to an Object type at runtime for field 'Query.me'. Either the 'Persona' type should provide a 'resolve_type' function or each possible type should provide an 'is_type_of' function.",
        locations=[SourceLocation(line=3, column=9)],
        path=['me'],
    )
]

Note

In the tutorial source we have the following fix applied so you will not see the error.

Since our query result is an Interface we need to tell GraphQL what type our object is. As the error states there are a couple ways to fix this. The easiest way is to provide a __typename field in the results since we are not returning an object that can functions added. The error assumes you have GraphQL type objects defined which with schema first we do not have (yet).

import pathlib
import cannula

from dashboard.core.config import config

async def resolve_me(info: cannula.ResolveInfo):
    return {
        "__typename": "User",
        "name": "Tiny Tim",
        "email": "tim@example.com",
        "id": "1",
    }

cannula_app = cannula.API(
    schema=pathlib.Path(config.root / "part1"),
    root_value={"me": resolve_me},
)

Now we get the results we wanted:

Results:

ExecutionResult(data={'me': {'id': '1', 'name': 'Tiny Tim'}}, errors=None)