Client library for making graphql calls.
Project description
A pythonic interface for making requests to a GraphQL server using pydantic V2 BaseModels to spare you from string manipulation.
Features
Use pydantic v2 BaseModels to specify graphql parameters and responses
As of gqlclient v2, standard library dataclasses are no longer supported
As of gqlclient v2, pydantic dataclasses are no longer supported
Create and execute GraphQL Queries based upon typed models
Create and execute GraphQL Mutations based upon typed models
Async support
Installation
pip install gqlclient
with asyncio support
pip install gqlclient[async]
for developers
pip install gqlclient[test]
pip install pre-commit
pre-commit install
Examples
Query
# limited to pydantic V2
from pydantic import BaseModel
from gqlclient import GraphQLClient
from gqlclient.request_wrap import wrap_request
from gqlclient.response_encoders import json_encoder
class GetRequest(BaseModel):
attr_one: str
attr_two: int
class Response(BaseModel):
attr_three: int
attr_four: str
# url for a running GQL server
client = GraphQLClient(gql_uri="http://localhost:8080/graphql")
query_params = GetRequest(attr_one="foo", attr_two=3)
query = client.get_query(query_base="baseType", query_response_cls=Response, query_parameters=wrap_request(query_params))
print(query)
# {'query': '{baseType(filterParams: {attr_one: "foo", attr_two: 3}){attr_three, attr_four} }'}
pseudo_response = client.execute_gql_query(query_base="baseType", query_response_cls=Response, query_parameters=wrap_request(query_params))
print(pseudo_response)
# [Response(attr_three=5, attr_four="bar")]
Mutation
# limited to pydantic V2
from pydantic import BaseModel
from gqlclient import GraphQLClient
class MutationRequest(BaseModel):
attr_one: str
attr_two: int
class Response(BaseModel):
attr_three: int
attr_four: str
# url for a running GQL server
client = GraphQLClient(gql_uri="http://localhost:8080/graphql")
mutation_params = MutationRequest(attr_one="foo", attr_two=3)
mutation = client.get_mutation(mutation_base="baseMutation", mutation_response_cls=Response, mutation_parameters=wrap_request(mutation_params))
print(mutation)
# {'query': 'mutation baseMutation {baseMutation(baseMuParams: {attr_one: "foo", attr_two: 3}){attr_three, attr_four} }', 'operationName': 'baseMutation'}
pseudo_response = client.execute_gql_mutation(mutation_base="baseMutation", mutation_response_cls=Response, mutation_parameters=wrap_request(mutation_params))
print(pseudo_response)
# [Response(attr_three=5, attr_four="bar")]
Encoders
# limited to pydantic V2
from pydantic import BaseModel
from gqlclient import GraphQLClient
from gqlclient import json_encoder
# url for a running GQL server
# set the default encoder to the json_encoder
client = GraphQLClient(gql_uri="http://localhost:8080/graphql", default_response_encoder=json_encoder)
class QueryResponse(BaseModel):
workflowId: int
workflowName: str
workflowDescription: str | None = None
response = client.execute_gql_query("workflows",QueryResponse)
print(response)
# Response is a json formatted string
# {"workflows": [{"workflowId": 1, "workflowName": "gql3_full - workflow_name", "workflowDescription": "gql3_full - workflow_description"}, {"workflowId": 2, "workflowName": "VBI base calibration", "workflowDescription": "The base set of calibration tasks for VBI."}]}
from gqlclient import basemodel_encoder
# for this call override the default encoder
response = client.execute_gql_query("workflows", QueryResponse, response_encoder=basemodel_encoder)
print(response)
# Response type is a list of BaseModels
# [QueryResponse(workflowId=1, workflowName='gql3_full - workflow_name', workflowDescription='gql3_full - workflow_description'), QueryResponse(workflowId=2, workflowName='VBI base calibration', workflowDescription='The base set of calibration tasks for VBI.')]
Best Practices
Simple Conversions between Camel Case and Snake Case
If your target GQL endpoint uses camelCase, follow these steps.
First, create a CamelHelper class:
# limited to pydantic V2
from pydantic import BaseModel
from pydantic import ConfigDict
from pydantic.alias_generators import to_camel
class CamelHelper(BaseModel):
"""
Helper Class.
Extend this class as if it were BaseModel.
Within the subclass, define the fields using snake_case.
Upon BaseModel instantiation, either snake_case or camelCase is valid input.
Normal model_dump will create a dict with snake_case keys.
Alias model_dump, with `by_alias=True`, will create a dict with camelCase keys.
"""
model_config = ConfigDict(
alias_generator=to_camel,
populate_by_name=True,
)
When defining your models, extend CamelHelper, instead of BaseModel. Define the attributes using snake_case.
class AliasSample(CamelHelper):
required_str: str
optional_float: float | None = None
# camelCase accepted upon creation
alias_sample = AliasSample(requiredStr="hello")
The internal key names will be snake_case. You can dump to a dict with snake_case keys:
alias_data_snake: dict = alias_sample.model_dump()
Or you can dump to a dict with camelCase keys:
alias_data_camel: dict = alias_sample.model_dump(by_alias=True)
Passing a dict as a dict
To pass a dict as a dict, the GQL Server must define the data type of the corresponding field as JSON. Note that JSON and JSONString are not the same thing. JSONString expects a json encoded string (frequently via json.dumps) which is transformed via json.loads. JSON expects an object and no transformation occurs.
Define the field as a dict within the model:
# limited to pydantic V2
from pydantic import BaseModel
class SampleCreateRequest(CamelHelper):
required_str: str | None = "Awesome"
payload: dict | None = None
dummy_payload = {
"key_str": "Party On, Wayne",
"key_int": 42,
"key_float": 3.141592,
"key_none": None,
"key_true": True,
"key_false": False,
}
create_request = SampleCreateRequest(
payload = dummy_payload
)
Execute the request:
# sample response
class SampleResponse(CamelHelper):
payload: dict | None = None
# url for a running GQL server
client = GraphQLClient(gql_uri="http://localhost:8080/graphql")
# assuming GQL server defines `payload` as `JSON`
pseudo_response = client.execute_gql_mutation(
mutation_base="sampleMutation",
mutation_response_cls=SampleResponse,
mutation_parameters=wrap_request(create_request)
)
assert isinstance(create_request.payload, dict)
assert isinstance(pseudo_response.payload, dict)
assert create_request.payload == pseudo_response.payload
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gqlclient-2.0.0.tar.gz.
File metadata
- Download URL: gqlclient-2.0.0.tar.gz
- Upload date:
- Size: 28.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e96004d15b1a4af204f32b8d3b611f1e8d9524f9a1ebd6101e50fecb1337281e
|
|
| MD5 |
5fa0aca8eb1cd86323bae05201dc062d
|
|
| BLAKE2b-256 |
f458ec82b06695eeb0d93bda7d65052404015f72c607531ededc6aec7bba47b9
|
File details
Details for the file gqlclient-2.0.0-py3-none-any.whl.
File metadata
- Download URL: gqlclient-2.0.0-py3-none-any.whl
- Upload date:
- Size: 30.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4bfe7161c21cc083c3a116faacd258cddbd0217eac6e78d13a41315cae652c5d
|
|
| MD5 |
846386cfe090b49bad2b78dff09e2ac1
|
|
| BLAKE2b-256 |
8f878692272053aeb595fd32321da25e1964d71844120fb5b78fb4402979657f
|