Test coverage Dependabot Documentation status
Development status Latest version License Supported python versions Black code style

Quiz

Capable GraphQL client for Python.

Features:

  • Sync/async compatible, pluggable HTTP clients.

  • Auto-generate typed and documented python APIs

  • ORM-like syntax to write GraphQL.

Note that this project is in an early alpha stage. Some features are not yet implemented (see the roadmap below), and it may be a little rough around the edges. If you encounter a problem or have a feature request, don’t hesitate to open an issue in the issue tracker.

Quickstart

A quick ‘n dirty request to GitHub’s new V4 API:

>>> import quiz
>>> query = '''
...   {
...     repository(owner: "octocat", name: "Hello-World") {
...       createdAt
...       description
...     }
...   }
... '''
>>> quiz.execute(query, url='https://api.github.com/graphql',
...              auth=('me', 'password'))
{"repository": ...}

Features

  1. Adaptability. Built on top of snug, quiz supports different HTTP clients

    import requests
    result = quiz.execute(query, ..., client=requests.Session())
    

    as well as async execution (optionally with aiohttp):

    result = await quiz.execute_async(query, ...)
    
  2. Typing. Convert a GraphQL schema into documented python classes:

    >>> schema = quiz.Schema.from_url('https://api.github.com/graphql',
    ...                               auth=('me', 'password'))
    >>> help(schema.Repository)
    class Repository(Node, ProjectOwner, Subscribable, Starrable,
     UniformResourceLocatable, RepositoryInfo, quiz.types.Object)
     |  A repository contains the content for a project.
     |
     |  Method resolution order:
     |      ...
     |
     |  Data descriptors defined here:
     |
     |  assignableUsers
     |      : UserConnection
     |      A list of users that can be assigned to issues in this repo
     |
     |  codeOfConduct
     |      : CodeOfConduct or None
     |      Returns the code of conduct for this repository
     ...
    
  3. GraphQL “ORM”. Write queries as you would with an ORM:

    >>> _ = quiz.SELECTOR
    >>> query = schema.query[
    ...     _
    ...     .repository(owner='octocat', name='Hello-World')[
    ...         _
    ...         .createdAt
    ...         .description
    ...     ]
    ... ]
    >>> str(query)
    query {
      repository(owner: "octocat", name: "Hello-World") {
        createdAt
        description
      }
    }
    
  4. Offline query validation. Use the schema to catch errors quickly:

    >>> schema.query[
    ...     _
    ...     .repository(owner='octocat', name='Hello-World')[
    ...         _
    ...         .createdAt
    ...         .foo
    ...         .description
    ...     ]
    ... ]
    SelectionError: SelectionError on "Query" at path "repository":
    
        SelectionError: SelectionError on "Repository" at path "foo":
    
            NoSuchField: field does not exist
    
  5. Deserialization into python objects. Responses are loaded into the schema’s types. Use . to access fields:

    >>> r = quiz.execute(query, ...)
    >>> r.repository.description
    "My first repository on GitHub!"
    >>> isinstance(r.repository, schema.Repository)
    True
    

    If you prefer the raw JSON response, you can always do:

    >>> quiz.execute(str(query), ...)
    {"repository": ...}
    

Installation

quiz and its dependencies are pure python. Installation is easy as:

pip install quiz

Contributing

After you’ve cloned the repo locally, set up the development environment with:

make init

For quick test runs, run:

pytest

To run all tests and checks on various python versions, run:

make test

Generate the docs with:

make docs

Pull requests welcome!

Preliminary roadmap

Feature

status

Input objects

v0.3.0

better query validation errors

v0.3.0

more examples in docs

v0.3.0

executing selection sets directly

v0.3.0

introspection fields (i.e. __typename)

v0.3.0

custom scalars for existing types (e.g. datetime)

v0.3.0

improve Object/Interface API

v0.3.0

value object docs

v0.3.0

Mutations & subscriptions

v0.3.0

Inline fragments

v0.3.0

Fragments and fragment spreads

v0.4.0

py2 unicode robustness

v0.4.0

Mixing in raw GraphQL

planned

Module autogeneration

planned

Type inference (e.g. enum values)

planned

Variables

planned

Directives

planned

Integer 32-bit limit

planned

converting names from camelcase to snake-case

idea

Autogenerate module .rst from schema

idea

Autogenerate module .py from schema

idea

Escaping python keywords

idea

Handling markdown in descriptions

idea

Warnings when using deprecated fields

idea

Handle optional types descriptions in schema

idea

Returning multiple validation errors at the same time

idea

Explicit ordering

idea

Contents

Release history

development

0.2.3 (2021-05-14)

  • Move to use poetry, github actions

0.2.2 (2020-12-05)

  • Official Python 3.9 support

0.2.1 (2020-09-11)

  • Drop Python 3.5 support

0.2.0 (2019-10-28)

  • Drop Python 2 support

  • Add Python 3.8 support

0.1.6 (2019-04-07)

  • Drop python 3.4 suport

0.1.5 (2019-03-16)

  • Include request/response metadata in responses (#95)

0.1.4 (2019-03-05)

  • Fixed issue with single-type unions (#100)

0.1.3 (2019-02-16)

  • Add request context to HTTPError (#82)

0.1.2 (2019-01-11)

  • Handle error responses without data correctly

0.1.1 (2018-10-30)

  • Fixed deserialization of Enum values

0.1.0 (2018-10-30)

  • Fixed handling of HTTP error status codes (#10)

  • Fix in validation exceptions (#11)

  • Implement custom scalars

  • Improvements to documentation

0.0.4 (2018-10-17)

  • Remove some unneeded fields from introspection query

  • Improvements to documentation

  • Small fixes to API, tests

0.0.3 (2018-09-23)

  • Established initial public API

  • Improved documentation, user guide

  • Field aliases

  • Deserialization

0.0.2 (2018-08-21)

  • Execution of basic GraphQL queries

  • Convert GraphQL schema to python types (undocumented)

  • Write GraphQL in python syntax (undocumented)

0.0.1

  • initial version

Indices and tables