Skip to main content

Async GraphQL Helper Library

Project description

Cannula

CircleCI Documentation Status codecov

GraphQL for people who like Python!

Why Cannula?

We wanted to make the world a better place, but we are programmers so we settled on making the web fun again. Too much attention has been given to Javascript client libraries. They all seem to compete on size and speed and features but most of them do not solve any of the actual problems you have. So while the todo application is quick and easy to follow the hard parts take a long time to complete.

Now a days if you want a fancy single page application you need to invest a good week or so planning out all the tools you will need to assemble your site. Every decision is full of sorrow and doubt as you google for the latest trends or how to setup unit tests. Or searching for a bootstrapped version of the library you like.

Using GraphQL you can simplify your web application stack and reduce dependencies to achieve the same customer experience without regret. By using a schema to define your application you can auto generate much of the code you need to interact with it.

Our Philosophy:

  1. Make your site easy to maintain.
  2. Document your code.
  3. Don't lock yourself into a framework.
  4. Be happy!

Installation

Requires Python 3.10 or greater! The only dependency is graphql-core.

pip3 install cannula

Quick Start

Here is a small hello world example:

import typing
import sys

import cannula

SCHEMA = """
    type Query {
        hello(who: String!): String
    }
"""

# The query resolver takes an `info` object and any arguments
# defined by the schema. Here we only accept a single argument `who`.
async def hello(
    info: cannula.ResolveInfo,
    who: str,
) -> str:
    # Here the field_name is 'hello' so we'll
    # return 'hello {who}!'
    return f"{info.field_name} {who}!"


# Basic API setup with the schema we defined and root_value
api = cannula.CannulaAPI(
    schema=SCHEMA,
    root_value={
        "hello": hello,  # Set the resolver function we defined
    }
)


# Pre-parse your query to speed up your requests.
SAMPLE_QUERY = cannula.gql(
    """
    query HelloWorld ($who: String!) {
        hello(who: $who)
    }
"""
)


def run_hello(who: str = "world"):
    return api.call_sync(SAMPLE_QUERY, variables={"who": who})


if __name__ == "__main__":
    who = "world"
    if len(sys.argv) > 1:
        who = sys.argv[1]

    print(run_hello(who))

Now you should see the results if you run the sample on the command line:

$ python3 examples/hello.py
ExecutionResult(
  data={'hello': "hello world!"},
  errors=None
)

$ python3 examples/hello.py Bob
ExecutionResult(
  data={"hello": "hello Bob!"},
  errors=None
)

Performance

We try to make sure cannula is as fast as possible. While real world benchmarks are always difficult we do have a simple test that attempts to show how cannula performs against other setups.

You can view the tests in performance. We have a simple function that returns data then compare the time it takes to return those results with a plan FastAPI app vs a GraphQL request. Then we try the same GraphQL request in both Cannula and Ariadne. Here is a sample of the output:

1000 iterations (lower is better)

test_performance.py::test_performance
performance test results:
fastapi: 0.4401752959993246
ariadne results: 1.8754248120003467
cannula results: 0.5984569250003915
PASSED
test_performance.py::test_performance_invalid_request
performance test results:
fastapi: 0.3655707629995959
ariadne results: 0.8345384459998968
cannula results: 0.42288053700031014
PASSED
test_performance.py::test_performance_invalid_query
performance test results:
fastapi: 0.3692567819998658
ariadne results: 2.08707908300039
cannula results: 0.4372879369993825
PASSED

As you can see Cannula is close to the raw performance of FastAPI. Granted real world results might be different as the way Cannula achieves it speed is by caching query validation results. This works best if you have a relatively fixed set of queries that are performed such as a UI that you or another team manages. If the requests are completely ad hoc like a public api then the results will not be as great.

Examples and Documentation

Documentation

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cannula-0.24.0.tar.gz (64.8 kB view details)

Uploaded Source

Built Distribution

cannula-0.24.0-py3-none-any.whl (84.4 kB view details)

Uploaded Python 3

File details

Details for the file cannula-0.24.0.tar.gz.

File metadata

  • Download URL: cannula-0.24.0.tar.gz
  • Upload date:
  • Size: 64.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.27.2

File hashes

Hashes for cannula-0.24.0.tar.gz
Algorithm Hash digest
SHA256 41c3390ef7eb89dea91ec93429aca2af202efa294b6473f6ffd81432445bad97
MD5 9bc91bff07ae7348dc689d419eae8726
BLAKE2b-256 a481e4f8f1fe6b2c516a41a4a0fb85c63f3c7de9d3361b87c4dfb7bf8450b9dc

See more details on using hashes here.

File details

Details for the file cannula-0.24.0-py3-none-any.whl.

File metadata

  • Download URL: cannula-0.24.0-py3-none-any.whl
  • Upload date:
  • Size: 84.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.27.2

File hashes

Hashes for cannula-0.24.0-py3-none-any.whl
Algorithm Hash digest
SHA256 798e480c68db5895d00cab048b069362c452a62f3fa101f4ebd39d3aa25d0041
MD5 ea316c912047f78d2cfb66d33ccd8eaf
BLAKE2b-256 09e3c0b7c6f907f8f52fe5f486575a87de6e694869211399910407adf5569395

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page