Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for custom scalar types #33

Closed

Conversation

ahussain3
Copy link

@ahussain3 ahussain3 commented Apr 30, 2018

In the GraphQL schema, it is possible to specify (CustomScalarTypes)[https://www.apollographql.com/docs/graphql-tools/scalars.html].

In order to specify a Custom Scalar Type, you need to define an object which implements the following interface:

  • serialize()
  • parse_literal()
  • parse_value()
    These methods allow GraphQL to translate between the serialized and deserialized versions of the custom scalar object.

However, when the GQL schema is passed around it includes only the names of the custom scalar types, and not the serialization/deserialization methods. After this PR is merged, you should be able to define your own classes on the client, and by giving them a parse_value() method you can use them as custom scalar types.

To configure the gql client to use your custom scalar types, you should do:

from gql import gql, Client
custom_types = {
    'DateTime': MyDateTimeClass
}

client = Client(schema=schema, transport=transport, custom_types=custom_types)
response = client.execute(query)

Move the GQLResponseParser into the gql library.

Each time a GQL query is made by the client, the response is passed through
ResponseParser.parse() where it is processed.

Configure your own custom scalars as follows:
```
    custom_scalars = {
        'SomeCustomScalar': <ScalarClass>
    }

    gql_client = GQLClient(transport=gql_transport,
                           schema=schema,
                           custom_scalars=custom_scalars)

    gql_client.execute(...)
```
<ScalarClass> should have a .parse_value(value) function

There are a few anti-patterns I have had to include in order to support
some new functionality that we require:
- client.execute now accepts `url` and `headers` as arguments, since we
  need to be able to set these on a per request basis. Previously they were
  supplied by the transport (which gets set only once at initialization
  time).
- As a consequence, the url supplied in to the transport goes unused if a
  url is passed in to `execute()`. It is a required field so I have to pass
  in a string, but it's not the best.
Awais Hussain added 7 commits May 1, 2018 12:52
The tests were copied over from a different repo and so were inconsistent
with the Star Wars schema we are using here. This PR should fix the tests
(although we are still using a remote schema rather than a local one, so
the tests run slowly becuase they need to make a http request each time).
The 'ResponseParser' name was confusing because it was too broad, and we
weren't really actually parsing the response. Hopefully this makes it
clearer that what we are actually doing it just adding support for custom
types.
Stick to the format of having a one line summary followed by more detailed
information.
Since we are now merging the headers specified in the transport with the
headers specified on a per request basis, we need to make sure the old
headers are of type `dict`, a `None` is not sufficient.
GQLServerError maps to errors which are generated on the backend server.
I.e. the server responds with a <200 OK> but an "errors" field is included
within the response. These are often user facing errors and should be
handled as such.

GQLSyntaxError maps to cases where either the query or the schema is
improperly formatted. This usually indicates a mistake in the code.
Previously we were using Python3.5+ type annotation syntax but this is not
backwards compatible so we are removing it.
@Cito Cito added this to the Version 3 milestone May 15, 2020
@Cito
Copy link
Member

Cito commented May 15, 2020

It's a bit sad that gql has been dormant and PRs like this did not receive feedback. I will try to get this merged into v3 (modern version), and if requested backport from there to v2 (legacy version). Also, I will probably make this a bit more general to support all kinds of leaf types, i.e. also Enum types.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature A new feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants