Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ assignees: ''

**Common problems**
- If you receive a TransportQueryError, it means the error is coming from the backend (See [Error Handling](https://gql.readthedocs.io/en/latest/advanced/error_handling.html)) and has probably nothing to do with gql
- If you use IPython (Jupyter, Spyder), then [you need to use the async version](https://gql.readthedocs.io/en/latest/async/async_usage.html#ipython)
- If you use IPython (Jupyter, Spyder), then [you need to use the async version](https://gql.readthedocs.io/en/latest/usage/async_usage.html#ipython)
- Before sending a bug report, please consider [activating debug logs](https://gql.readthedocs.io/en/latest/advanced/logging.html) to see the messages exchanged between the client and the backend

**Describe the bug**
Expand Down
56 changes: 49 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# GQL

This is a GraphQL client for Python 3.8+.
Plays nicely with `graphene`, `graphql-core`, `graphql-js` and any other GraphQL implementation compatible with the spec.
This is a GraphQL client for Python.
Plays nicely with `graphene`, `graphql-core`, `graphql-js` and any other GraphQL implementation
compatible with the [GraphQL specification](https://spec.graphql.org).

GQL architecture is inspired by `React-Relay` and `Apollo-Client`.

Expand Down Expand Up @@ -37,7 +38,7 @@ The complete documentation for GQL can be found at
* AWS AppSync realtime protocol (experimental)
* Possibility to [validate the queries locally](https://gql.readthedocs.io/en/latest/usage/validation.html) using a GraphQL schema provided locally or fetched from the backend using an instrospection query
* Supports GraphQL queries, mutations and [subscriptions](https://gql.readthedocs.io/en/latest/usage/subscriptions.html)
* Supports [sync or async usage](https://gql.readthedocs.io/en/latest/async/index.html), [allowing concurrent requests](https://gql.readthedocs.io/en/latest/advanced/async_advanced_usage.html#async-advanced-usage)
* Supports [sync](https://gql.readthedocs.io/en/latest/usage/sync_usage.html) or [async](https://gql.readthedocs.io/en/latest/usage/async_usage.html) usage, [allowing concurrent requests](https://gql.readthedocs.io/en/latest/advanced/async_advanced_usage.html#async-advanced-usage)
* Supports [File uploads](https://gql.readthedocs.io/en/latest/usage/file_upload.html)
* Supports [Custom scalars / Enums](https://gql.readthedocs.io/en/latest/usage/custom_scalars_and_enums.html)
* Supports [Batching requests](https://gql.readthedocs.io/en/latest/advanced/batching_requests.html)
Expand All @@ -57,17 +58,17 @@ pip install "gql[all]"

## Usage

### Basic usage
### Sync usage

```python
from gql import gql, Client
from gql import Client, gql
from gql.transport.aiohttp import AIOHTTPTransport

# Select your transport with a defined url endpoint
transport = AIOHTTPTransport(url="https://countries.trevorblades.com/")

# Create a GraphQL client using the defined transport
client = Client(transport=transport, fetch_schema_from_transport=True)
client = Client(transport=transport)

# Provide a GraphQL query
query = gql(
Expand Down Expand Up @@ -95,7 +96,48 @@ $ python basic_example.py

> **WARNING**: Please note that this basic example won't work if you have an asyncio event loop running. In some
> python environments (as with Jupyter which uses IPython) an asyncio event loop is created for you. In that case you
> should use instead the [async usage example](https://gql.readthedocs.io/en/latest/async/async_usage.html#async-usage).
> should use instead the [async usage example](https://gql.readthedocs.io/en/latest/usage/async_usage.html#async-usage).

### Async usage

```python
import asyncio

from gql import Client, gql
from gql.transport.aiohttp import AIOHTTPTransport


async def main():

# Select your transport with a defined url endpoint
transport = AIOHTTPTransport(url="https://countries.trevorblades.com/graphql")

# Create a GraphQL client using the defined transport
client = Client(transport=transport)

# Provide a GraphQL query
query = gql(
"""
query getContinents {
continents {
code
name
}
}
"""
)

# Using `async with` on the client will start a connection on the transport
# and provide a `session` variable to execute queries on this connection
async with client as session:

# Execute the query
result = await session.execute(query)
print(result)


asyncio.run(main())
```

## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md)
Expand Down
18 changes: 0 additions & 18 deletions docs/async/async_intro.rst

This file was deleted.

10 changes: 0 additions & 10 deletions docs/async/index.rst

This file was deleted.

34 changes: 18 additions & 16 deletions docs/code_examples/aiohttp_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,29 @@

async def main():

# Select your transport with a defined url endpoint
transport = AIOHTTPTransport(url="https://countries.trevorblades.com/graphql")

# Create a GraphQL client using the defined transport
client = Client(transport=transport)

# Provide a GraphQL query
query = gql(
"""
query getContinents {
continents {
code
name
}
}
"""
)

# Using `async with` on the client will start a connection on the transport
# and provide a `session` variable to execute queries on this connection
async with Client(
transport=transport,
fetch_schema_from_transport=True,
) as session:

# Execute single query
query = gql(
"""
query getContinents {
continents {
code
name
}
}
"""
)
async with client as session:

# Execute the query
result = await session.execute(query)
print(result)

Expand Down
2 changes: 1 addition & 1 deletion docs/code_examples/aiohttp_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
transport = AIOHTTPTransport(url="https://countries.trevorblades.com/")

# Create a GraphQL client using the defined transport
client = Client(transport=transport, fetch_schema_from_transport=True)
client = Client(transport=transport)

# Provide a GraphQL query
query = gql(
Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

# -- Project information -----------------------------------------------------

project = 'gql 3'
copyright = '2020, graphql-python.org'
project = 'gql'
copyright = '2025, graphql-python.org'
author = 'graphql-python.org'

# The full version, including alpha/beta/rc tags
Expand Down
5 changes: 2 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Welcome to GQL 3 documentation!
===============================
GQL documentation
=================

Contents
--------
Expand All @@ -9,7 +9,6 @@ Contents

intro
usage/index
async/index
transports/index
advanced/index
gql-cli/intro
Expand Down
6 changes: 3 additions & 3 deletions docs/intro.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Introduction
============

`GQL 3`_ is a `GraphQL`_ Client for Python 3.8+ which plays nicely with other
`GQL`_ is a `GraphQL`_ Client for Python which plays nicely with other
graphql implementations compatible with the spec.

Under the hood, it uses `GraphQL-core`_ which is a Python port of `GraphQL.js`_,
Expand All @@ -10,7 +10,7 @@ the JavaScript reference implementation for GraphQL.
Installation
------------

You can install GQL 3 and all the extra dependencies using pip_::
You can install GQL and all the extra dependencies using pip_::

pip install "gql[all]"

Expand Down Expand Up @@ -93,7 +93,7 @@ Please check the `Contributing`_ file to learn how to make a good pull request.
.. _GraphQL: https://graphql.org/
.. _GraphQL-core: https://github.com/graphql-python/graphql-core
.. _GraphQL.js: https://github.com/graphql/graphql-js
.. _GQL 3: https://github.com/graphql-python/gql
.. _GQL: https://github.com/graphql-python/gql
.. _pip: https://pip.pypa.io/
.. _GitHub repository for gql: https://github.com/graphql-python/gql
.. _Contributing: https://github.com/graphql-python/gql/blob/master/CONTRIBUTING.md
Expand Down
24 changes: 21 additions & 3 deletions docs/async/async_usage.rst → docs/usage/async_usage.rst
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
.. _async_usage:

Async Usage
Async usage
===========

On previous versions of GQL, the code was `sync` only , it means that when you ran
`execute` on the Client, you could do nothing else in the current Thread and had to wait for
an answer or a timeout from the backend to continue. The only http library was `requests`, allowing only sync usage.

From the version 3 of GQL, we support `sync` and `async` :ref:`transports <transports>` using `asyncio`_.

With the :ref:`async transports <async_transports>`, there is now the possibility to execute GraphQL requests
asynchronously, :ref:`allowing to execute multiple requests in parallel if needed <async_advanced_usage>`.

If you don't care or need async functionality, it is still possible, with :ref:`async transports <async_transports>`,
to run the `execute` or `subscribe` methods directly from the Client
(as described in the :ref:`Sync Usage <sync_usage>` example) and GQL will execute the request
in a synchronous manner by running an asyncio event loop itself.

This won't work though if you already have an asyncio event loop running. In that case you should use the async
methods.

Example
-------

If you use an :ref:`async transport <async_transports>`, you can use GQL asynchronously using `asyncio`_.

* put your code in an asyncio coroutine (method starting with :code:`async def`)
* use :code:`async with client as session:` to connect to the backend and provide a session instance
* use the :code:`await` keyword to execute requests: :code:`await session.execute(...)`
* then run your coroutine in an asyncio event loop by running :code:`asyncio.run`

Example:

.. literalinclude:: ../code_examples/aiohttp_async.py

IPython
Expand Down
3 changes: 2 additions & 1 deletion docs/usage/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Usage
.. toctree::
:maxdepth: 2

basic_usage
sync_usage
async_usage
validation
subscriptions
variables
Expand Down
63 changes: 55 additions & 8 deletions docs/usage/subscriptions.rst
Original file line number Diff line number Diff line change
@@ -1,29 +1,76 @@
Subscriptions
=============

Using the :ref:`websockets transport <websockets_transport>`, it is possible to execute GraphQL subscriptions:
Using the :ref:`websockets transport <websockets_transport>`, it is possible to execute GraphQL subscriptions,
either using the sync or async usage.

The async usage is recommended for any non-trivial tasks (it allows efficient concurrent queries and subscriptions).

See :ref:`Async permanent session <async_permanent_session>` and :ref:`Async advanced usage <async_advanced_usage>`
for more advanced examples.

.. note::

The websockets transport can also execute queries or mutations, it is not restricted to subscriptions.

Sync
----

.. code-block:: python

from gql import gql, Client
from gql import Client, gql
from gql.transport.websockets import WebsocketsTransport

# Select your transport with a defined url endpoint
transport = WebsocketsTransport(url='wss://your_server/graphql')

client = Client(
transport=transport,
fetch_schema_from_transport=True,
)
# Create a GraphQL client using the defined transport
client = Client(transport=transport)

# Provide a GraphQL subscription query
query = gql('''
subscription yourSubscription {
...
}
''')

# Connect and subscribe to the results using a simple 'for'
for result in client.subscribe(query):
print (result)

.. note::
Async
-----

.. code-block:: python

import asyncio

from gql import Client, gql
from gql.transport.websockets import WebsocketsTransport


async def main():

# Select your transport with a defined url endpoint
transport = WebsocketsTransport(url='wss://your_server/graphql')

# Create a GraphQL client using the defined transport
client = Client(transport=transport)

# Provide a GraphQL subscription query
query = gql('''
subscription yourSubscription {
...
}
''')

# Using `async with` on the client will start a connection on the transport
# and provide a `session` variable to execute queries on this connection
async with client as session:

# Then get the results using 'async for'
async for result in client.subscribe(query):
print (result)


The websockets transport can also execute queries or mutations, it is not restricted to subscriptions
asyncio.run(main())
9 changes: 4 additions & 5 deletions docs/usage/basic_usage.rst → docs/usage/sync_usage.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
.. _basic_usage:
.. _sync_usage:

Basic usage
-----------
Sync usage
==========

In order to execute a GraphQL request against a GraphQL API:
To execute a GraphQL request against a GraphQL API:

* create your gql :ref:`transport <transports>` in order to choose the destination url
and the protocol used to communicate with it
Expand All @@ -18,4 +18,3 @@ In order to execute a GraphQL request against a GraphQL API:
Please note that this basic example won't work if you have an asyncio event loop running. In some
python environments (as with Jupyter which uses IPython) an asyncio event loop is created for you.
In that case you should use instead the :ref:`Async Usage example<async_usage>`.

Loading