Skip to content
Draft
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
13 changes: 13 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
websocket-client = "*"
requests = "*"

[requires]
python_version = "3.8"
72 changes: 72 additions & 0 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

126 changes: 93 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# py-graphql-client
Dead-simple to use GraphQL client over websocket. Using the
[apollo-transport-ws](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md)
protocol.

Dead-simple to use GraphQL client over websocket. Using the [apollo-transport-ws](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md) protocol. Supports HTTP too.

## Install

Expand All @@ -11,60 +10,57 @@ pip install py-graphql-client

## Examples

### Setup subscriptions super easily
### Super easy to setup and run subscriptions

```python
from graphql_client import GraphQLClient
from graphql_client import GraphQLClient, WebsocketTransport

transport = WebsocketTransport('ws://localhost:8080/graphql')
client = GraphQLClient(transport)

ws = GraphQLClient('ws://localhost:8080/graphql')
def callback(_id, data):
print("got new data..")
print(f"msg id: {_id}. data: {data}")
print(f"Got new data on: Operation ID: {_id}. Data: {data}")

query = """
subscription {
notifications {
latest_notifications = """
subscription getLatestNotifications($limit: Int!) {
notifications (last: $limit) {
id
title
content
}
}
"""
sub_id = ws.subscribe(query, callback=callback)
sub_id = client.subscribe(latest_notifications, variables={'limit': 5}, callback=callback)

...
# later stop the subscription
ws.stop_subscribe(sub_id)
ws.close()
client.stop_subscription(sub_id)
client.close()
```

### Variables can be passed
### Set session context via HTTP headers

```python
from graphql_client import GraphQLClient
from graphql_client import GraphQLClient, WebsocketTransport

ws = GraphQLClient('ws://localhost:8080/graphql')
def callback(_id, data):
print("got new data..")
print(f"msg id: {_id}. data: {data}")
transport = WebsocketTransport('ws://localhost:8080/graphql')
client = GraphQLClient(transport)

query = """
subscription ($limit: Int!) {
notifications (order_by: {created: "desc"}, limit: $limit) {
id
title
content
}
}
"""
sub_id = ws.subscribe(query, variables={'limit': 10}, callback=callback)
...

client.set_session(headers={'Authorization': 'Bearer xxxxx'})

sub_id = client.subscribe(latest_notifications, variables={'limit': 5}, callback=callback)
```

### Normal queries and mutations work too

```python
from graphql_client import GraphQLClient

ws = GraphQLClient('ws://localhost:8080/graphql')
transport = WebsocketTransport('ws://localhost:8080/graphql')
client = GraphQLClient('ws://localhost:8080/graphql')

query = """
query ($limit: Int!) {
notifications (order_by: {created: "desc"}, limit: $limit) {
Expand All @@ -76,11 +72,75 @@ query = """
"""
res = ws.query(query, variables={'limit': 10})
print(res)
ws.close()

mutation = """
mutation ($username: String!) {
registerUser (username: $username) {
userId
username
}
}
"""
res = client.mutate(mutation, variables={'username': 'alice'})
print(res)

client.close()
```

### Using HTTP transport

```python
from graphql_client import GraphQLClient, HttpTransport

# first create a `HttpTransport`
transport = HttpTransport('https://countries.trevorblades.com/')
# then create a `GraphQLClient` which uses the `HttpTransport`
client = GraphQLClient(transport)

query = """
query getCountry($code: ID!) {
country(code: $code) {
code
name
capital
}
}
"""

client.set_session(headers={'Authorization': 'Bearer xxxx'})
res = client.query(query, variables={'code': 'IN'})
print(res)

# unset all headers
client.set_session(headers=None)
res = client.query(query, variables={'code': 'IN'})
print(res)

# mutations work too

create_user = """
mutation createUser($username: String!, $password: String!) {
insertUser(username: $username, password: $password) {
userId
username
}
}
"""
res = client.mutate(create_user, variables={'username': 'alice', 'password': 'p@55w0rd'})
print(res)

client.close()
```

## TODO
- tests
- support http as well
- should use asyncio websocket library?

<!--
## Features
- Websockets and GraphQL subscriptions supported!
- Flexible transport option (choose either `HttpTransport` or `WebsocketTransport`)
- Run mutiple subscriptions in parallel over a single websocket connection
- Re-authorize on subscriptions without closing the websocket connection
- HTTP session manager
-->
48 changes: 0 additions & 48 deletions example.py

This file was deleted.

25 changes: 25 additions & 0 deletions examples/http_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from graphql_client import GraphQLClient, HttpTransport

# first create a `HttpTransport`
transport = HttpTransport('https://countries.trevorblades.com/')

# then create a `GraphQLClient` which uses the `HttpTransport`
client = GraphQLClient(transport)

query = """
query getCountry($code: ID!) {
country(code: $code) {
code
name
capital
}
}
"""

# changing session context via headers
client.set_session(headers={'Authorization': 'Bearer xxxx'})

# # This is a blocking call, you receive response in the `res` variable
res = client.query(query, variables={'code': 'IN'})
print(res)
client.close()
39 changes: 39 additions & 0 deletions examples/ws_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import time
import random

from graphql_client import GraphQLClient, WebsocketTransport

transport = WebsocketTransport('wss://hge-testing.herokuapp.com/v1/graphql')
client = GraphQLClient(transport)

query = """
query getUser($userId: Int!) {
users(where:{u_id: {_eq: $userId}}) {
u_id
u_name
}
}
"""

res = client.query(query, variables={'userId': 2})
print(res)

subscription_query = """
subscription getUser {
user (id: 2) {
id
username
}
}
"""

def my_callback(_id, data):
print(f"<Subs Callback>: Got data for Sub ID: {_id}. Data: {data}")

sub_id = client.subscribe(subscription_query, variables={'userId': 2}, callback=my_callback)

# do some operation while the subscription is running...
time.sleep(3)

client.stop_subscription(sub_id)
client.close()
Loading