Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

codecov

Documentation Status

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

Download files

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

Source Distribution

gqlclient-2.1.0rc1.tar.gz (29.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gqlclient-2.1.0rc1-py3-none-any.whl (31.0 kB view details)

Uploaded Python 3

File details

Details for the file gqlclient-2.1.0rc1.tar.gz.

File metadata

  • Download URL: gqlclient-2.1.0rc1.tar.gz
  • Upload date:
  • Size: 29.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.15

File hashes

Hashes for gqlclient-2.1.0rc1.tar.gz
Algorithm Hash digest
SHA256 b003f49e4d5813338c52b421e90baf64afb1ce938369cb4e2ca91d359ee85a25
MD5 fda88c9aaa8de29e26933d9ce3bbf3a3
BLAKE2b-256 bf9033b7b860d534348a54f3c9d918a3a0dbcea58c57e4dc04070f1a87bdb6ec

See more details on using hashes here.

File details

Details for the file gqlclient-2.1.0rc1-py3-none-any.whl.

File metadata

  • Download URL: gqlclient-2.1.0rc1-py3-none-any.whl
  • Upload date:
  • Size: 31.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.15

File hashes

Hashes for gqlclient-2.1.0rc1-py3-none-any.whl
Algorithm Hash digest
SHA256 9328072fbb10afc18bec357be8c8a85b295ce3e8e826053f1d4316925833a8ed
MD5 ed7d3ad8fe2595f30591bc83a73b3849
BLAKE2b-256 86339bf72ab877c4c8ba423527271ba20fcd5b659de47d6c1b403e7ccd67fbea

See more details on using hashes here.

Release history Release notifications | RSS feed

2.1.0

2 files

This release

2.1.0rc1 This release

2 files

2.0.0

2 files

1.2.3

2 files

1.2.2

2 files

1.2.1

2 files

1.2.0

2 files

1.1.1

2 files

1.1.0

2 files

1.0.2

1 file

1.0.1

1 file

1.0.0

1 file

0.9.6

1 file

0.9.5

1 file

0.9.4

1 file

0.9.3

1 file

0.9.2

1 file

0.9.1

1 file

0.9.0

1 file

0.8.2

1 file

0.8.1

1 file

0.8.0

1 file

0.7.3

1 file

0.7.2

1 file

0.7.1

1 file

0.6

1 file

0.5

1 file

0.4

1 file

0.2

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page