Skip to main content

TypeGQL

A Python GraphQL library that makes use of type hinting and concurrency support with the new async/await syntax. With the help of type hints and dataclass it’s easy to build a GraphQL schema using nothing but Python objects and primitives

Consider the following:

from graphql import (
    GraphQLSchema, GraphQLObjectType, GraphQLField, GraphQLString)

schema = GraphQLSchema(
    query=GraphQLObjectType(
        name='RootQueryType',
        fields={
            'hello': GraphQLField(
                GraphQLString,
                resolve=lambda obj, info: 'world')
        }))

Versus:

from dataclasses import dataclass
from typegql import Schema

@dataclass(init=False)
class RootQuery:
    hello: str

def resolve_hello(info):
    return 'world

 schema = Schema(query=RootQuery)

Clearly the second one looks more “Pythonic” and it’s easier to maintain for complex structures

Installation

pip install typegql

Usage

The following demonstrates how to use typegql for implementing a GraphQL API for a library of books. The example can be found in typegql/core/examples and you can run it with Sanic by executing python <path_to_example>/server.py

Define your query

from dataclasses import dataclass
from typing import List
from typegql import Connection
from typegql.examples.library.types import Author, Category
from typegql.examples.library.types import Book
from typegql.examples.library import db


@dataclass(init=False, repr=False)
class Query:
    books: List[Book]
    authors: List[Author]
    categories: List[Category]

    books_connection: Connection[Book]

    async def resolve_authors(self, info, **kwargs):
        return db.get('authors')

    async def resolve_books(self, info, **kwargs):
        return db.get('books')

    async def resolve_categories(self, info, **kwargs):
        return db.get('categories')

   async def resolve_books_connection(self, info, **kwargs):
        data = db.get('books')
        return {
            'edges': [{
                'node': node
            } for node in data]}

Define your types

from dataclasses import dataclass, field
from datetime import datetime
from decimal import Decimal
from enum import Enum
from typing import List

from examples.library import db


class Gender(Enum):
    MALE = 'male'
    FEMALE = 'female'


@dataclass
class GeoLocation:
    latitude: Decimal
    longitude: Decimal


@dataclass
class Author:
    """Person that is usually a writer"""

    id: ID = field(metadata={'readonly': True})
    name: str
    gender: Optional[Gender] = None
    geo: Optional[GeoLocation] = None
    books: Optional[List[Book]] = None


@dataclass
class Category:
    id: ID = field(metadata={'readonly': True})
    name: str


@dataclass
class Book:
    """A book... for reading :|"""

    id: ID = field(metadata={'readonly': True})
    author_id: ID
    title: str
    author: Optional[Author] = field(default=None, metadata={'description': 'The author of this book'})
    categories: Optional[List[Category]] = None
    published: Optional[datetime] = None
    tags: Optional[List[str]] = None

    def __post_init__(self):
        self.published = datetime.strptime(self.published, '%Y-%m-%d %H:%M:%S')

    async def resolve_author(self, info):
        data = filter(lambda x: x['id'] == self.author_id, db.get('authors'))
        data = next(data)
        author = Author(**data)
        author.gender = Gender(author.gender)
        if 'geo' in data:
            author.geo = GeoLocation(**data.get('geo'))
        return author

    async def resolve_categories(self, selections, name=None):
        data = filter(lambda x: x['id'] in self.categories, db.get('categories'))
        for d in data:  # showcasing async generator
            yield Category(**d)

    def resolve_tags(self, selections):
        return ['testing', 'purpose']

Run your query

from typegql import Schema
from examples.library.query import Query


schema = Schema(Query)
query = '''
query BooksConnection {
  books_connection {
    edges {
      node {
        id
        title
        published
        author {
          id
          name
        }
      }
    }
  }
}
'''

async def run():
    result = await schema.run(query)

Client

TypeGQL supports DSL client for working with a GraphQL API. The client automatically converts snake to camelcase. Set camelcase=False if this is not desired.

pip install typegql[client]

For example:

from typegql.client import Client

async with Client(url, camelcase=True) as client:
    await client.introspection()
    dsl = client.dsl
    query = dsl.Query.books_connection.select(dsl.BooksConnection.total_count)
    doc = dsl.query(query)

    status, result = await client.execute(doc)

Change Log

4.0.2 [2020-04-06]

  • updates graphql-core to 3.1.0

4.0.1 [2020-03-17]

  • fixes enum return value

4.0.0 [2020-03-16]

  • BREAKING CHANGES:
    • Schema now accepts a more granular list of custom graphql types. Signature is:

def __init__(self,
         query: Type,
         mutation: Optional[Type] = None,
         subscription: Optional[Type] = None,
         scalars: Optional[GraphQLScalarMap] = None,
         enums: Optional[GraphQLEnumMap] = None,
         interfaces: Optional[GraphQLInterfaceMap] = None,
         query_types: Optional[GraphQLObjectTypeMap] = None,
         mutation_types: Optional[GraphQLInputObjectTypeMap] = None,
         camelcase=True):

3.1.0 [2020-01-29]

  • fixes an issue with camelcase parameters when a load method is provided

3.0.9 [2020-01-13]

  • fix client execution function

  • update dsl selections to work with FrozenList

3.0.8 [2020-01-07]

  • added ability to ignore attributes in building the schema by using field(metadata={‘skip’: True}). This can be useful when you don’t want to expose certain fields in GraphQL, like a user’s password for example.

3.0.5 [2019-12-16]

  • added support for subscriptions

3.0.4 [2019-12-04]

  • updates graphql-core-next to grapqhl-core >= 3

  • use Sequence instead of List where possible

3.0.3 [2019-11-29]

  • fixed a bug where a custom connection arguments don’t include the relay pagination arguments as well

3.0.2 [2019-11-26]

  • PEP 561 compliant

3.0.1 [2019-11-26]

  • BREAKING: Removed Graph as a baseclass

  • now makes use of dataclasses.dataclass and dataclasess.fields for building the Schema

  • bug fixing and improvements

2.0.9 [2019-10-29]

  • changed the name of an input object from ObjectMuation to ObjectInput

2.0.8 [2019-10-15]

  • allows forward reference between graph types (ie: Book has an author and an Author has books).

    this only works with python 3.7(using from __future__ import annotations, or python 3.8

2.0.6 [2019-06-24]

  • updates uvloop dependency

2.0.5 [2019-04-24]

  • fixed a bug when sending introspection schema

2.0.4 [2019-04-24]

  • updates assert for introspection add message with status and result

  • adds support for enum objects in resolve_field_velue_or_error

2.0.3 [2019-02-08]

  • changes Connection, Edge, Node and PageInfo to interfaces IConnection, IEdge, etc.

  • implements default Connection and PageInfo objects

  • removes has_next, has_previous from PageInfo

2.0.1 [2019-01-19]

  • all properties that don’t have a Field instance assigned to them will be ignored by the Schema

  • updates docs & example to reflect 2.0 changes

  • fixed a bug when using a List argument in mutations

1.0.7 [2018-12-09]

  • bug fixing

  • adds support for camelcase in Client

1.0.1 [2018-11-19]

  • adds support for client DSL

Initial

TODO

  • testing

  • travis

  • more testing

  • please help with testing :|

Metadata

Release files for typegql 4.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for typegql 4.0.2
File Size Uploaded
typegql-4.0.2.tar.gz 18.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for typegql 4.0.2
File Interpreter ABI Platform
typegql-4.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 36.9 kB

Release files / typegql-4.0.2.tar.gz

Download URL typegql-4.0.2.tar.gz
Size 18.4 kB
Tags Source
SHA-256 checksum
How to use checksums
5cc022a4405191aa899e89029389c4edf8d00d55a8151fed196b0885024462f7
BLAKE2b-256 checksum
How to use checksums
36879e466aa830a44ef6910af678c25863d211e570846fbee19a6bc0d337dbd0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.0.5 CPython/2.7.16 Darwin/19.3.0

Release files / typegql-4.0.2-py3-none-any.whl

Download URL typegql-4.0.2-py3-none-any.whl
Size 18.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
25652746dcf0c8abfafc4f0251858207528dec90df1dc23852ed37e5f819d30e
BLAKE2b-256 checksum
How to use checksums
9199f9ed7e53357fd1374b1c89d7f16bbf53e8537f64777e66fae75d99315959
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.0.5 CPython/2.7.16 Darwin/19.3.0

Release history Release notifications | RSS feed

This release

4.0.2 This release

2 release files

4.0.1

2 release files

4.0.0

2 release files

3.1.0

2 release files

3.0.9

2 release files

3.0.8

2 release files

3.0.7

2 release files

3.0.6

2 release files

3.0.5

2 release files

3.0.4

2 release files

3.0.3

2 release files

3.0.2

2 release files

3.0.1

2 release files

2.0.11

2 release files

2.0.10

2 release files

2.0.9

2 release files

2.0.8

2 release files

2.0.7

2 release files

2.0.6

2 release files

2.0.5

2 release files

2.0.4

2 release files

2.0.3

2 release files

2.0.2

2 release files

2.0.1

2 release files

1.1.0

2 release files

1.0.13

2 release files

1.0.12

2 release files

1.0.11

2 release files

1.0.10

2 release files

1.0.9

2 release files

1.0.8

2 release files

1.0.7

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page