Objects

Create an instance of pyql.Object:

Example = Object(
    'Example',
    description='An example object',
    fields={
        'my_str': str,
        'my_int': int,
        'my_float': float,
        'my_bool': bool,
        'my_id': ID,
    })

Note

Field names will be converted automatically from snake_case to camelCase for you, so you can use the right naming convention in your Python / JavaScript code.

Field from resolver

You can define a field quickly by using the Object.field decorator. Field type and arguments will be picked up automatically by inspecting type annotations:

Example = Object('Example')

@Example.field('hello')
def resolve_hello(root, info, name: str = 'stranger') -> str:
    return 'Hello ' + name

Python types will be converted automatically to GraphQL types.

If you need to use custom types, simply annotate your resolver accordingly.

Resolver returning object

Object instances can be instantiated and treated as normal Python objects.

Example = Object('Example', {'foo': str, 'bar': str})

Query = Object('Query')

@Query.field('example')
def resolve_example(root, info) -> Example:
    return Example(foo='A', bar='B')

schema = Schema(query=Query)

Default resolver

The default resolver for a field will simply attempt to pick the same-named attribute from the root object.

This way you don’t have to define something like this for every simple field you have on your objects:

@User.field('name')
def resolve_user_name(root, info) -> str:
    return root.name

@User.field('email')
def resolve_user_email(root, info) -> str:
    return root.email

# ...

Namespace fields

Sometimes it’s convenient to “namespace” objects. Problem is, field resolution will stop when an object resolver returns None, so you need to define your resolvers like this:

from pyql import ID, Object

User = Object('User', {'id': ID, 'name': str})

Users = Object('Users')

@Users.field('list')
def resolve_list_users(root, info) -> List[User]:
    pass

@Users.field('search')
def resolve_search_users(root, info, query: str) -> List[User]:
    pass

Query = Object('Query')

@Query.field('users')
def resolve_users(root, info) -> Users:
    # Needs to return something other than None, or the resolvers
    # for list / search will never be called
    return Users()

You can replace the resolve_users definition with:

Query.namespace_field('users', Users)

This allows you to run queries like:

{
    users {
        list {
            id
            name
        }
    }
}

Container types

Objects can be “instantiated” to create objects you can return from your resolvers:

MyObject = Object('MyObject', fields={'foo': str, 'bar': str})

@Query.field('example')
def resolve_example(root, info) -> MyObject:
    return MyObject(foo='FOO', bar='BAR')

This will also ensure types are understood correctly when using interfaces.