async def is_type_of_with_async_error():
        PetType = GraphQLInterfaceType("Pet", {"name": GraphQLField(GraphQLString)})

        DogType = GraphQLObjectType(
            "Dog",
            {
                "name": GraphQLField(GraphQLString),
                "woofs": GraphQLField(GraphQLBoolean),
            },
            interfaces=[PetType],
            is_type_of=is_type_of_error,
        )

        CatType = GraphQLObjectType(
            "Cat",
            {
                "name": GraphQLField(GraphQLString),
                "meows": GraphQLField(GraphQLBoolean),
            },
            interfaces=[PetType],
            is_type_of=get_is_type_of(Cat),
        )

        schema = GraphQLSchema(
            GraphQLObjectType(
                "Query",
                {
                    "pets": GraphQLField(
                        GraphQLList(PetType),
                        resolve=lambda *_args: [
                            Dog("Odie", True),
                            Cat("Garfield", False),
                        ],
                    )
                },
            ),
            types=[CatType, DogType],
        )

        query = """
            {
              pets {
                name
                ... on Dog {
                  woofs
                }
                ... on Cat {
                  meows
                }
              }
            }
            """

        result = await graphql(schema, query)
        # Note: we get two errors, because first all types are resolved
        # and only then they are checked sequentially
        assert result.data == {"pets": [None, None]}
        assert list(map(format_error, result.errors)) == [
            {
                "message": "We are testing this error",
                "locations": [(3, 15)],
                "path": ["pets", 0],
            },
            {
                "message": "We are testing this error",
                "locations": [(3, 15)],
                "path": ["pets", 1],
            },
        ]
Beispiel #2
0
from pytest import raises  # type: ignore

from graphql.error import GraphQLError
from graphql.language import (
    parse,
    DocumentNode,
    OperationDefinitionNode,
    OperationTypeDefinitionNode,
    SchemaDefinitionNode,
)
from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString
from graphql.utilities import get_operation_root_type

query_type = GraphQLObjectType("FooQuery",
                               {"field": GraphQLField(GraphQLString)})

mutation_type = GraphQLObjectType("FooMutation",
                                  {"field": GraphQLField(GraphQLString)})

subscription_type = GraphQLObjectType("FooSubscription",
                                      {"field": GraphQLField(GraphQLString)})


def get_operation_node(doc: DocumentNode) -> OperationDefinitionNode:
    operation_node = doc.definitions[0]
    assert isinstance(operation_node, OperationDefinitionNode)
    return operation_node


def describe_get_operation_root_type():
    def gets_a_query_type_for_an_unnamed_operation_definition_node():
    def resolve_type_allows_resolving_with_type_name():
        PetType = GraphQLInterfaceType(
            "Pet",
            {"name": GraphQLField(GraphQLString)},
            resolve_type=get_type_resolver({
                Dog: "Dog",
                Cat: "Cat"
            }),
        )

        DogType = GraphQLObjectType(
            "Dog",
            {
                "name": GraphQLField(GraphQLString),
                "woofs": GraphQLField(GraphQLBoolean),
            },
            interfaces=[PetType],
        )

        CatType = GraphQLObjectType(
            "Cat",
            {
                "name": GraphQLField(GraphQLString),
                "meows": GraphQLField(GraphQLBoolean),
            },
            interfaces=[PetType],
        )

        schema = GraphQLSchema(
            GraphQLObjectType(
                "Query",
                {
                    "pets":
                    GraphQLField(
                        GraphQLList(PetType),
                        resolve=lambda *_:
                        [Dog("Odie", True),
                         Cat("Garfield", False)],
                    )
                },
            ),
            types=[CatType, DogType],
        )

        query = """
            {
              pets {
                name
                ... on Dog {
                  woofs
                }
                ... on Cat {
                  meows
                }
              }
            }"""

        result = graphql_sync(schema, query)
        assert result == (
            {
                "pets": [
                    {
                        "name": "Odie",
                        "woofs": True
                    },
                    {
                        "name": "Garfield",
                        "meows": False
                    },
                ]
            },
            None,
        )
Beispiel #4
0
 def stringifies_fields():
     assert str(GraphQLField(GraphQLNonNull(GraphQLString))) == "Field: String!"
     assert str(GraphQLField(GraphQLList(GraphQLInt))) == "Field: [Int]"
    async def resolve_type_on_union_yields_useful_error():
        HumanType = GraphQLObjectType('Human',
                                      {'name': GraphQLField(GraphQLString)})

        DogType = GraphQLObjectType(
            'Dog', {
                'name': GraphQLField(GraphQLString),
                'woofs': GraphQLField(GraphQLBoolean)
            })

        CatType = GraphQLObjectType(
            'Cat', {
                'name': GraphQLField(GraphQLString),
                'meows': GraphQLField(GraphQLBoolean)
            })

        PetType = GraphQLUnionType('Pet', [DogType, CatType],
                                   resolve_type=get_type_resolver({
                                       Dog:
                                       DogType,
                                       Cat:
                                       CatType,
                                       Human:
                                       HumanType
                                   }))

        schema = GraphQLSchema(
            GraphQLObjectType(
                'Query', {
                    'pets':
                    GraphQLField(GraphQLList(PetType),
                                 resolve=lambda *_: [
                                     Dog('Odie', True),
                                     Cat('Garfield', False),
                                     Human('Jon')
                                 ])
                }))

        query = """
            {
              pets {
                ... on Dog {
                  name
                  woofs
                }
                ... on Cat {
                  name
                  meows
                }
              }
            }
            """

        result = await graphql(schema, query)
        assert result.data == {
            'pets': [{
                'name': 'Odie',
                'woofs': True
            }, {
                'name': 'Garfield',
                'meows': False
            }, None]
        }

        assert len(result.errors) == 1
        assert format_error(result.errors[0]) == {
            'message': "Runtime Object type 'Human'"
            " is not a possible type for 'Pet'.",
            'locations': [(3, 15)],
            'path': ['pets', 2]
        }
Beispiel #6
0
def get_first(args, *keys):
    for key in keys:
        if key in args:
            return args[key]

    return None


QueryType = GraphQLObjectType(
    name='Query',
    fields={
        'colorEnum': GraphQLField(
            type=ColorType,
            args={
                'fromEnum': GraphQLArgument(ColorType),
                'fromInt': GraphQLArgument(GraphQLInt),
                'fromString': GraphQLArgument(GraphQLString)
            },
            resolver=lambda value, args, context, info: get_first(args, 'fromInt', 'fromString', 'fromEnum')
        ),
        'colorInt': GraphQLField(
            type=GraphQLInt,
            args={
                'fromEnum': GraphQLArgument(ColorType),
                'fromInt': GraphQLArgument(GraphQLInt),
            },
            resolver=lambda value, args, context, info: get_first(args, 'fromInt', 'fromEnum')
        )
    }
)
Beispiel #7
0
 def accepts_a_lambda_as_an_object_field_resolver():
     obj_type = GraphQLObjectType(
         "SomeObject",
         {"f": GraphQLField(ScalarType, resolve=lambda _obj, _info: {})},
     )
     assert obj_type.fields
    GraphQLInputObjectType,
    GraphQLInt,
    GraphQLInterfaceType,
    GraphQLList,
    GraphQLNonNull,
    GraphQLObjectType,
    GraphQLSchema,
    GraphQLString,
    GraphQLUnionType,
)
from graphql.type.definition import is_input_type, is_output_type

BlogImage = GraphQLObjectType(
    "Image",
    {
        "url": GraphQLField(GraphQLString),
        "width": GraphQLField(GraphQLInt),
        "height": GraphQLField(GraphQLInt),
    },
)

BlogAuthor = GraphQLObjectType(
    "Author",
    lambda: {
        "id": GraphQLField(GraphQLString),
        "name": GraphQLField(GraphQLString),
        "pic": GraphQLField(
            BlogImage,
            args={
                "width": GraphQLArgument(GraphQLInt),
                "height": GraphQLArgument(GraphQLInt),
Beispiel #9
0
def test_synchronous_error_nulls_out_error_subtrees():
    # type: () -> None
    ast = parse("""
    {
        sync
        syncError
        syncReturnError
        syncReturnErrorList
        asyncBasic
        asyncReject
        asyncEmptyReject
        asyncReturnError
    }
    """)

    class Data:
        def sync(self):
            # type: () -> str
            return "sync"

        def syncError(self):
            # type: () -> NoReturn
            raise Exception("Error getting syncError")

        def syncReturnError(self):
            # type: () -> Exception
            return Exception("Error getting syncReturnError")

        def syncReturnErrorList(self):
            # type: () -> List[Union[Exception, str]]
            return [
                "sync0",
                Exception("Error getting syncReturnErrorList1"),
                "sync2",
                Exception("Error getting syncReturnErrorList3"),
            ]

        def asyncBasic(self):
            # type: () -> Promise
            return resolved("async")

        def asyncReject(self):
            # type: () -> Promise
            return rejected(Exception("Error getting asyncReject"))

        def asyncEmptyReject(self):
            # type: () -> Promise
            return rejected(Exception("An unknown error occurred."))

        def asyncReturnError(self):
            # type: () -> Promise
            return resolved(Exception("Error getting asyncReturnError"))

    schema = GraphQLSchema(query=GraphQLObjectType(
        name="Type",
        fields={
            "sync": GraphQLField(GraphQLString),
            "syncError": GraphQLField(GraphQLString),
            "syncReturnError": GraphQLField(GraphQLString),
            "syncReturnErrorList": GraphQLField(GraphQLList(GraphQLString)),
            "asyncBasic": GraphQLField(GraphQLString),
            "asyncReject": GraphQLField(GraphQLString),
            "asyncEmptyReject": GraphQLField(GraphQLString),
            "asyncReturnError": GraphQLField(GraphQLString),
        },
    ))

    def sort_key(item):
        # type: (Dict[str, Any]) -> Tuple[int, int]
        locations = item["locations"][0]
        return (locations["line"], locations["column"])

    def handle_results(result):
        # type: (ExecutionResult) -> None
        assert result.data == {
            "asyncBasic": "async",
            "asyncEmptyReject": None,
            "asyncReject": None,
            "asyncReturnError": None,
            "sync": "sync",
            "syncError": None,
            "syncReturnError": None,
            "syncReturnErrorList": ["sync0", None, "sync2", None],
        }
        assert sorted(list(map(
            format_error, result.errors)), key=sort_key) == sorted(
                [
                    {
                        "locations": [{
                            "line": 4,
                            "column": 9
                        }],
                        "path": ["syncError"],
                        "message": "Error getting syncError",
                    },
                    {
                        "locations": [{
                            "line": 5,
                            "column": 9
                        }],
                        "path": ["syncReturnError"],
                        "message": "Error getting syncReturnError",
                    },
                    {
                        "locations": [{
                            "line": 6,
                            "column": 9
                        }],
                        "path": ["syncReturnErrorList", 1],
                        "message": "Error getting syncReturnErrorList1",
                    },
                    {
                        "locations": [{
                            "line": 6,
                            "column": 9
                        }],
                        "path": ["syncReturnErrorList", 3],
                        "message": "Error getting syncReturnErrorList3",
                    },
                    {
                        "locations": [{
                            "line": 8,
                            "column": 9
                        }],
                        "path": ["asyncReject"],
                        "message": "Error getting asyncReject",
                    },
                    {
                        "locations": [{
                            "line": 9,
                            "column": 9
                        }],
                        "path": ["asyncEmptyReject"],
                        "message": "An unknown error occurred.",
                    },
                    {
                        "locations": [{
                            "line": 10,
                            "column": 9
                        }],
                        "path": ["asyncReturnError"],
                        "message": "Error getting asyncReturnError",
                    },
                ],
                key=sort_key,
            )

    handle_results(execute(schema, ast, Data(), executor=ThreadExecutor()))
    pets: Optional[List[Union[Dog, Cat]]]
    friends: Optional[List[Union[Dog, Cat, "Person"]]]

    def __init__(
        self,
        name: str,
        pets: Optional[List[Union[Dog, Cat]]] = None,
        friends: Optional[List[Union[Dog, Cat, "Person"]]] = None,
    ):
        self.name = name
        self.pets = pets
        self.friends = friends


NamedType = GraphQLInterfaceType("Named",
                                 {"name": GraphQLField(GraphQLString)})

LifeType = GraphQLInterfaceType(
    "Life",
    lambda: {"progeny": GraphQLField(GraphQLList(LifeType))}  # type: ignore
)

MammalType = GraphQLInterfaceType(
    "Mammal",
    lambda: {
        "progeny": GraphQLField(GraphQLList(MammalType)),  # type: ignore
        "mother": GraphQLField(MammalType),  # type: ignore
        "father": GraphQLField(MammalType),  # type: ignore
    },
    interfaces=[LifeType],
)
Beispiel #11
0
    GraphQLString,
    GraphQLUnionType,
)
from graphql.type.directives import (
    DirectiveLocation,
    GraphQLDirective,
    GraphQLIncludeDirective,
    GraphQLSkipDirective,
)
from graphql.validation import validate

Being = GraphQLInterfaceType(
    "Being",
    {
        "name":
        GraphQLField(GraphQLString,
                     {"surname": GraphQLArgument(GraphQLBoolean)})
    },
)

Pet = GraphQLInterfaceType(
    "Pet",
    {
        "name":
        GraphQLField(GraphQLString,
                     {"surname": GraphQLArgument(GraphQLBoolean)})
    },
)

Canine = GraphQLInterfaceType(
    "Canine",
    {
Beispiel #12
0
    GraphQLScalarType,
)
from graphql.type.directives import (
    DirectiveLocation,
    GraphQLDirective,
    GraphQLIncludeDirective,
    GraphQLSkipDirective,
)
from graphql.validation import ValidationRule, SDLValidationRule
from graphql.validation.validate import validate, validate_sdl

Being = GraphQLInterfaceType(
    "Being",
    {
        "name":
        GraphQLField(GraphQLString,
                     {"surname": GraphQLArgument(GraphQLBoolean)})
    },
)

Mammal = GraphQLInterfaceType(
    "Mammal",
    lambda: {
        "mother": GraphQLField(Mammal),  # type: ignore
        "father": GraphQLField(Mammal),  # type: ignore
    },
    interfaces=[],
)

Pet = GraphQLInterfaceType(
    "Pet",
    {
    async def resolve_type_can_be_caught():
        PetType = GraphQLInterfaceType(
            "Pet", {"name": GraphQLField(GraphQLString)}, resolve_type=is_type_of_error
        )

        DogType = GraphQLObjectType(
            "Dog",
            {
                "name": GraphQLField(GraphQLString),
                "woofs": GraphQLField(GraphQLBoolean),
            },
            interfaces=[PetType],
        )

        CatType = GraphQLObjectType(
            "Cat",
            {
                "name": GraphQLField(GraphQLString),
                "meows": GraphQLField(GraphQLBoolean),
            },
            interfaces=[PetType],
        )

        schema = GraphQLSchema(
            GraphQLObjectType(
                "Query",
                {
                    "pets": GraphQLField(
                        GraphQLList(PetType),
                        resolve=lambda *_: [Dog("Odie", True), Cat("Garfield", False)],
                    )
                },
            ),
            types=[CatType, DogType],
        )

        query = """{
          pets {
            name
            ... on Dog {
              woofs
            }
            ... on Cat {
              meows
            }
          }
        }"""

        result = await graphql(schema, query)
        assert result == (
            {"pets": [None, None]},
            [
                {
                    "message": "We are testing this error",
                    "locations": [(2, 11)],
                    "path": ["pets", 0],
                },
                {
                    "message": "We are testing this error",
                    "locations": [(2, 11)],
                    "path": ["pets", 1],
                },
            ],
        )
    async def is_type_of_used_to_resolve_runtime_type_for_union():
        DogType = GraphQLObjectType(
            "Dog",
            {
                "name": GraphQLField(GraphQLString),
                "woofs": GraphQLField(GraphQLBoolean),
            },
            is_type_of=get_is_type_of(Dog),
        )

        CatType = GraphQLObjectType(
            "Cat",
            {
                "name": GraphQLField(GraphQLString),
                "meows": GraphQLField(GraphQLBoolean),
            },
            is_type_of=get_is_type_of(Cat),
        )

        PetType = GraphQLUnionType("Pet", [CatType, DogType])

        schema = GraphQLSchema(
            GraphQLObjectType(
                "Query",
                {
                    "pets": GraphQLField(
                        GraphQLList(PetType),
                        resolve=lambda *_args: [
                            Dog("Odie", True),
                            Cat("Garfield", False),
                        ],
                    )
                },
            )
        )

        query = """
            {
              pets {
                ... on Dog {
                  name
                  woofs
                }
                ... on Cat {
                  name
                  meows
                }
              }
            }
            """

        result = await graphql(schema, query)
        assert result == (
            {
                "pets": [
                    {"name": "Odie", "woofs": True},
                    {"name": "Garfield", "meows": False},
                ]
            },
            None,
        )
Beispiel #15
0
    async def nulls_out_error_subtrees():
        doc = """{
              syncOk
              syncError
              syncRawError
              syncReturnError
              syncReturnErrorList
              asyncOk
              asyncError
              asyncRawError
              asyncReturnError
              asyncReturnErrorWithExtensions
            }"""

        # noinspection PyPep8Naming,PyMethodMayBeStatic
        class Data:
            def syncOk(self, _info):
                return 'sync ok'

            def syncError(self, _info):
                raise GraphQLError('Error getting syncError')

            def syncRawError(self, _info):
                raise Exception('Error getting syncRawError')

            def syncReturnError(self, _info):
                return Exception('Error getting syncReturnError')

            def syncReturnErrorList(self, _info):
                return [
                    'sync0',
                    Exception('Error getting syncReturnErrorList1'), 'sync2',
                    Exception('Error getting syncReturnErrorList3')
                ]

            async def asyncOk(self, _info):
                return 'async ok'

            async def asyncError(self, _info):
                raise Exception('Error getting asyncError')

            async def asyncRawError(self, _info):
                raise Exception('Error getting asyncRawError')

            async def asyncReturnError(self, _info):
                return GraphQLError('Error getting asyncReturnError')

            async def asyncReturnErrorWithExtensions(self, _info):
                return GraphQLError(
                    'Error getting asyncReturnErrorWithExtensions',
                    extensions={'foo': 'bar'})

        ast = parse(doc)

        schema = GraphQLSchema(
            GraphQLObjectType(
                'Type', {
                    'syncOk': GraphQLField(GraphQLString),
                    'syncError': GraphQLField(GraphQLString),
                    'syncRawError': GraphQLField(GraphQLString),
                    'syncReturnError': GraphQLField(GraphQLString),
                    'syncReturnErrorList': GraphQLField(
                        GraphQLList(GraphQLString)),
                    'asyncOk': GraphQLField(GraphQLString),
                    'asyncError': GraphQLField(GraphQLString),
                    'asyncErrorWithExtensions': GraphQLField(GraphQLString),
                    'asyncRawError': GraphQLField(GraphQLString),
                    'asyncReturnError': GraphQLField(GraphQLString),
                    'asyncReturnErrorWithExtensions':
                    GraphQLField(GraphQLString)
                }))

        assert await execute(schema, ast, Data()) == ({
            'syncOk':
            'sync ok',
            'syncError':
            None,
            'syncRawError':
            None,
            'syncReturnError':
            None,
            'syncReturnErrorList': ['sync0', None, 'sync2', None],
            'asyncOk':
            'async ok',
            'asyncError':
            None,
            'asyncRawError':
            None,
            'asyncReturnError':
            None,
            'asyncReturnErrorWithExtensions':
            None
        }, [{
            'message': 'Error getting syncError',
            'locations': [(3, 15)],
            'path': ['syncError']
        }, {
            'message': 'Error getting syncRawError',
            'locations': [(4, 15)],
            'path': ['syncRawError']
        }, {
            'message': 'Error getting syncReturnError',
            'locations': [(5, 15)],
            'path': ['syncReturnError']
        }, {
            'message': 'Error getting syncReturnErrorList1',
            'locations': [(6, 15)],
            'path': ['syncReturnErrorList', 1]
        }, {
            'message': 'Error getting syncReturnErrorList3',
            'locations': [(6, 15)],
            'path': ['syncReturnErrorList', 3]
        }, {
            'message': 'Error getting asyncError',
            'locations': [(8, 15)],
            'path': ['asyncError']
        }, {
            'message': 'Error getting asyncRawError',
            'locations': [(9, 15)],
            'path': ['asyncRawError']
        }, {
            'message': 'Error getting asyncReturnError',
            'locations': [(10, 15)],
            'path': ['asyncReturnError']
        }, {
            'message': 'Error getting asyncReturnErrorWithExtensions',
            'locations': [(11, 15)],
            'path': ['asyncReturnErrorWithExtensions'],
            'extensions': {
                'foo': 'bar'
            }
        }])
Beispiel #16
0
def test_executes_arbitary_code():
    # type: () -> None
    class Data(object):
        a = "Apple"
        b = "Banana"
        c = "Cookie"
        d = "Donut"
        e = "Egg"

        @property
        def f(self):
            # type: () -> Promise
            return resolved("Fish")

        def pic(self, size=50):
            # type: (int) -> Promise
            return resolved("Pic of size: {}".format(size))

        def deep(self):
            # type: () -> DeepData
            return DeepData()

        def promise(self):
            # type: () -> Promise
            return resolved(Data())

    class DeepData(object):
        a = "Already Been Done"
        b = "Boring"
        c = ["Contrived", None, resolved("Confusing")]

        def deeper(self):
            # type: () -> List[Union[None, Data, Promise]]
            return [Data(), None, resolved(Data())]

    ast = parse("""
        query Example($size: Int) {
            a,
            b,
            x: c
            ...c
            f
            ...on DataType {
                pic(size: $size)
                promise {
                    a
                }
            }
            deep {
                a
                b
                c
                deeper {
                    a
                    b
                }
            }
        }
        fragment c on DataType {
            d
            e
        }
    """)

    expected = {
        "a": "Apple",
        "b": "Banana",
        "x": "Cookie",
        "d": "Donut",
        "e": "Egg",
        "f": "Fish",
        "pic": "Pic of size: 100",
        "promise": {
            "a": "Apple"
        },
        "deep": {
            "a":
            "Already Been Done",
            "b":
            "Boring",
            "c": ["Contrived", None, "Confusing"],
            "deeper": [
                {
                    "a": "Apple",
                    "b": "Banana"
                },
                None,
                {
                    "a": "Apple",
                    "b": "Banana"
                },
            ],
        },
    }

    DataType = GraphQLObjectType(
        "DataType",
        lambda: {
            "a":
            GraphQLField(GraphQLString),
            "b":
            GraphQLField(GraphQLString),
            "c":
            GraphQLField(GraphQLString),
            "d":
            GraphQLField(GraphQLString),
            "e":
            GraphQLField(GraphQLString),
            "f":
            GraphQLField(GraphQLString),
            "pic":
            GraphQLField(
                args={"size": GraphQLArgument(GraphQLInt)},
                type=GraphQLString,
                resolver=lambda obj, info, **args: obj.pic(args["size"]),
            ),
            "deep":
            GraphQLField(DeepDataType),
            "promise":
            GraphQLField(DataType),
        },
    )

    DeepDataType = GraphQLObjectType(
        "DeepDataType",
        {
            "a": GraphQLField(GraphQLString),
            "b": GraphQLField(GraphQLString),
            "c": GraphQLField(GraphQLList(GraphQLString)),
            "deeper": GraphQLField(GraphQLList(DataType)),
        },
    )

    schema = GraphQLSchema(query=DataType)

    def handle_result(result):
        # type: (ExecutionResult) -> None
        assert not result.errors
        assert result.data == expected

    handle_result(
        execute(
            schema,
            ast,
            Data(),
            variable_values={"size": 100},
            operation_name="Example",
            executor=ThreadExecutor(),
        ))
    handle_result(
        execute(schema,
                ast,
                Data(),
                variable_values={"size": 100},
                operation_name="Example"))
Beispiel #17
0
    async def executes_arbitrary_code():

        # noinspection PyMethodMayBeStatic,PyMethodMayBeStatic
        class Data:
            def a(self, _info):
                return 'Apple'

            def b(self, _info):
                return 'Banana'

            def c(self, _info):
                return 'Cookie'

            def d(self, _info):
                return 'Donut'

            def e(self, _info):
                return 'Egg'

            f = 'Fish'

            def pic(self, _info, size=50):
                return f'Pic of size: {size}'

            def deep(self, _info):
                return DeepData()

            def promise(self, _info):
                return promise_data()

        # noinspection PyMethodMayBeStatic,PyMethodMayBeStatic
        class DeepData:
            def a(self, _info):
                return 'Already Been Done'

            def b(self, _info):
                return 'Boring'

            def c(self, _info):
                return ['Contrived', None, 'Confusing']

            def deeper(self, _info):
                return [Data(), None, Data()]

        async def promise_data():
            await asyncio.sleep(0)
            return Data()

        doc = """
            query Example($size: Int) {
              a,
              b,
              x: c
              ...c
              f
              ...on DataType {
                pic(size: $size)
                promise {
                  a
                }
              }
              deep {
                a
                b
                c
                deeper {
                  a
                  b
                }
              }
            }

            fragment c on DataType {
              d
              e
            }
            """

        ast = parse(doc)
        expected = ({
            'a': 'Apple',
            'b': 'Banana',
            'x': 'Cookie',
            'd': 'Donut',
            'e': 'Egg',
            'f': 'Fish',
            'pic': 'Pic of size: 100',
            'promise': {
                'a': 'Apple'
            },
            'deep': {
                'a':
                'Already Been Done',
                'b':
                'Boring',
                'c': ['Contrived', None, 'Confusing'],
                'deeper': [{
                    'a': 'Apple',
                    'b': 'Banana'
                }, None, {
                    'a': 'Apple',
                    'b': 'Banana'
                }]
            }
        }, None)

        DataType = GraphQLObjectType(
            'DataType', lambda: {
                'a':
                GraphQLField(GraphQLString),
                'b':
                GraphQLField(GraphQLString),
                'c':
                GraphQLField(GraphQLString),
                'd':
                GraphQLField(GraphQLString),
                'e':
                GraphQLField(GraphQLString),
                'f':
                GraphQLField(GraphQLString),
                'pic':
                GraphQLField(GraphQLString,
                             args={'size': GraphQLArgument(GraphQLInt)},
                             resolve=lambda obj, info, size: obj.pic(
                                 info, size)),
                'deep':
                GraphQLField(DeepDataType),
                'promise':
                GraphQLField(DataType)
            })

        DeepDataType = GraphQLObjectType(
            'DeepDataType', {
                'a': GraphQLField(GraphQLString),
                'b': GraphQLField(GraphQLString),
                'c': GraphQLField(GraphQLList(GraphQLString)),
                'deeper': GraphQLList(DataType)
            })

        schema = GraphQLSchema(DataType)

        assert await execute(schema,
                             ast,
                             Data(),
                             variable_values={'size': 100},
                             operation_name='Example') == expected
    def builds_a_schema_with_an_enum():
        food_enum = GraphQLEnumType(
            "Food",
            {
                "VEGETABLES":
                GraphQLEnumValue(1, description="Foods that are vegetables."),
                "FRUITS":
                GraphQLEnumValue(2),
                "OILS":
                GraphQLEnumValue(3, deprecation_reason="Too fatty."),
            },
            description="Varieties of food stuffs",
        )

        schema = GraphQLSchema(
            GraphQLObjectType(
                "EnumFields",
                {
                    "food":
                    GraphQLField(
                        food_enum,
                        args={
                            "kind":
                            GraphQLArgument(food_enum,
                                            description="what kind of food?")
                        },
                        description="Repeats the arg you give it",
                    )
                },
            ))

        introspection = introspection_from_schema(schema)
        client_schema = build_client_schema(introspection)

        second_introspection = introspection_from_schema(client_schema)
        assert second_introspection == introspection

        # It's also an Enum type on the client.
        client_food_enum = assert_enum_type(client_schema.get_type("Food"))

        # Client types do not get server-only values, so the values mirror the names,
        # rather than using the integers defined in the "server" schema.
        values = {
            name: value.to_kwargs()
            for name, value in client_food_enum.values.items()
        }
        assert values == {
            "VEGETABLES": {
                "value": "VEGETABLES",
                "description": "Foods that are vegetables.",
                "deprecation_reason": None,
                "extensions": {},
                "ast_node": None,
            },
            "FRUITS": {
                "value": "FRUITS",
                "description": None,
                "deprecation_reason": None,
                "extensions": {},
                "ast_node": None,
            },
            "OILS": {
                "value": "OILS",
                "description": None,
                "deprecation_reason": "Too fatty.",
                "extensions": {},
                "ast_node": None,
            },
        }
Beispiel #19
0
 def fields():
     nonlocal calls
     calls += 1
     return {"f": GraphQLField(ScalarType)}
    async def promise_to_change_the_number(self,
                                           new_number: int) -> NumberHolder:
        await asyncio.sleep(0)
        return self.immediately_change_the_number(new_number)

    def fail_to_change_the_number(self, newNumber: int):
        raise RuntimeError(f"Cannot change the number to {newNumber}")

    async def promise_and_fail_to_change_the_number(self, newNumber: int):
        await asyncio.sleep(0)
        self.fail_to_change_the_number(newNumber)


numberHolderType = GraphQLObjectType("NumberHolder",
                                     {"theNumber": GraphQLField(GraphQLInt)})

# noinspection PyPep8Naming
schema = GraphQLSchema(
    GraphQLObjectType("Query",
                      {"numberHolder": GraphQLField(numberHolderType)}),
    GraphQLObjectType(
        "Mutation",
        {
            "immediatelyChangeTheNumber":
            GraphQLField(
                numberHolderType,
                args={"newNumber": GraphQLArgument(GraphQLInt)},
                resolve=lambda obj, _info, newNumber: obj.
                immediately_change_the_number(newNumber),
            ),
Beispiel #21
0
 def accepts_an_interface_type_defining_resolve_type():
     assert GraphQLInterfaceType("AnotherInterface", {"f": GraphQLField(ScalarType)})
Beispiel #22
0
from graphql.type import (GraphQLField, GraphQLObjectType, GraphQLSchema,
                          GraphQLString)

Query = GraphQLObjectType(
    'Query', lambda: {
        'hello': GraphQLField(GraphQLString, resolver=lambda *_: "World"),
    })

schema = GraphQLSchema(Query)
def get_graphql_schema_from_schema_graph(schema_graph,
                                         class_to_field_type_overrides,
                                         hidden_classes):
    """Return a GraphQL schema object corresponding to the schema of the given schema graph.

    Args:
        schema_graph: SchemaGraph
        class_to_field_type_overrides: dict, class name -> {field name -> field type},
                                       (string -> {string -> GraphQLType}). Used to override the
                                       type of a field in the class where it's first defined and all
                                       the class's subclasses.
        hidden_classes: set of strings, classes to not include in the GraphQL schema.

    Returns:
        tuple of (GraphQL schema object, GraphQL type equivalence hints dict).
        The tuple is of type (GraphQLSchema, {GraphQLObjectType -> GraphQLUnionType}).
    """
    _validate_overriden_fields_are_not_defined_in_superclasses(
        class_to_field_type_overrides, schema_graph)

    # The field types of subclasses must also be overridden.
    # Remember that the result returned by get_subclass_set(class_name) includes class_name itself.
    inherited_field_type_overrides = _get_inherited_field_types(
        class_to_field_type_overrides, schema_graph)

    graphql_types = OrderedDict()
    type_equivalence_hints = OrderedDict()

    # For each vertex class, construct its analogous GraphQL type representation.
    for vertex_cls_name in sorted(schema_graph.vertex_class_names):
        vertex_cls = schema_graph.get_element_by_class_name(vertex_cls_name)
        if vertex_cls_name in hidden_classes:
            continue

        inherited_field_type_overrides.setdefault(vertex_cls_name, dict())
        field_type_overrides = inherited_field_type_overrides[vertex_cls_name]

        # We have to use delayed type binding here, because some of the type references
        # are circular: if an edge connects vertices of types A and B, then
        # GraphQL type A has a List[B] field, and type B has a List[A] field.
        # To avoid the circular dependency, GraphQL allows us to initialize the types
        # initially without their field information, and fill in their field information
        # later using a lambda function as the second argument to GraphQLObjectType.
        # This lambda function will be called on each type after all types are created
        # in their initial blank state.
        #
        # However, 'cls_name' is a variable that would not be correctly bound
        # if we naively tried to construct a lambda in-place, because Python lambdas
        # are not closures. Instead, call a function with 'cls_name' as an argument,
        # and have that function construct and return the required lambda.
        field_specification_lambda = _create_field_specification(
            schema_graph, graphql_types, field_type_overrides, hidden_classes,
            vertex_cls_name)

        # Abstract classes are interfaces, concrete classes are object types.
        current_graphql_type = None
        if vertex_cls.abstract:
            # "fields" is a kwarg in the interface constructor, even though
            # it's a positional arg in the object type constructor.
            current_graphql_type = GraphQLInterfaceType(
                vertex_cls_name, fields=field_specification_lambda)
        else:
            # For similar reasons as the field_specification_lambda,
            # we need to create an interface specification lambda function that
            # specifies the interfaces implemented by this type.
            interface_specification_lambda = _create_interface_specification(
                schema_graph, graphql_types, hidden_classes, vertex_cls_name)

            # N.B.: Ignore the "is_type_of" argument below, it is simply a circumvention of
            #       a sanity check inside the GraphQL library. The library assumes that we'll use
            #       its execution system, so it complains that we don't provide a means to
            #       differentiate between different implementations of the same interface.
            #       We don't care, because we compile the GraphQL query to a database query.
            current_graphql_type = GraphQLObjectType(
                vertex_cls_name,
                field_specification_lambda,
                interfaces=interface_specification_lambda,
                is_type_of=lambda: None)

        graphql_types[vertex_cls_name] = current_graphql_type

    # For each vertex class, construct all union types representations.
    for vertex_cls_name in sorted(schema_graph.vertex_class_names):
        vertex_cls = schema_graph.get_element_by_class_name(vertex_cls_name)
        if vertex_cls_name in hidden_classes:
            continue

        vertex_cls_subclasses = schema_graph.get_subclass_set(vertex_cls_name)
        if not vertex_cls.abstract and len(vertex_cls_subclasses) > 1:
            # In addition to creating this class' corresponding GraphQL type, we'll need a
            # union type to represent it when it appears as the endpoint of an edge.
            union_type_name = _get_union_type_name(vertex_cls_subclasses)

            # For similar reasons as the field_specification_lambda,
            # we need to create a union type specification lambda function that specifies
            # the types that this union type is composed of.
            type_specification_lambda = _create_union_types_specification(
                schema_graph, graphql_types, hidden_classes, vertex_cls_name)

            union_type = GraphQLUnionType(union_type_name,
                                          types=type_specification_lambda)
            graphql_types[union_type_name] = union_type
            type_equivalence_hints[graphql_types[vertex_cls_name]] = union_type

    # Include all abstract non-vertex classes whose only non-abstract subclasses are vertices.
    for non_graph_cls_name in sorted(schema_graph.non_graph_class_names):
        if non_graph_cls_name in hidden_classes:
            continue
        if not schema_graph.get_element_by_class_name(
                non_graph_cls_name).abstract:
            continue

        cls_subclasses = schema_graph.get_subclass_set(non_graph_cls_name)
        # No need to add the possible abstract class if it doesn't have subclasses besides itself.
        if len(cls_subclasses) > 1:
            all_non_abstract_subclasses_are_vertices = True

            # Check all non-abstract subclasses are vertices.
            for subclass_name in cls_subclasses:
                subclass = schema_graph.get_element_by_class_name(
                    subclass_name)
                if subclass_name != non_graph_cls_name:
                    if not subclass.abstract and not subclass.is_vertex:
                        all_non_abstract_subclasses_are_vertices = False
                        break

            if all_non_abstract_subclasses_are_vertices:
                # Add abstract class as an interface.
                inherited_field_type_overrides.setdefault(
                    non_graph_cls_name, dict())
                field_type_overrides = inherited_field_type_overrides[
                    non_graph_cls_name]
                field_specification_lambda = _create_field_specification(
                    schema_graph, graphql_types, field_type_overrides,
                    hidden_classes, non_graph_cls_name)
                graphql_type = GraphQLInterfaceType(
                    non_graph_cls_name, fields=field_specification_lambda)
                graphql_types[non_graph_cls_name] = graphql_type

    if not graphql_types:
        raise EmptySchemaError(
            u'After evaluating all subclasses of V, we were not able to find '
            u'visible schema data to import into the GraphQL schema object')

    # Create the root query GraphQL type. Consists of all non-union classes, i.e.
    # all non-abstract classes (as GraphQL types) and all abstract classes (as GraphQL interfaces).
    RootSchemaQuery = GraphQLObjectType(
        'RootSchemaQuery',
        OrderedDict([(name, GraphQLField(GraphQLList(value)))
                     for name, value in sorted(six.iteritems(graphql_types),
                                               key=lambda x: x[0])
                     if not isinstance(value, GraphQLUnionType)]))

    schema = GraphQLSchema(RootSchemaQuery, directives=DIRECTIVES)

    # Note that the GraphQLSchema reconstructs the set of types in the schema by recursively
    # searching through the fields of the RootSchemaQuery. Since union types can only appear in the
    # fields of other types as edges, union types with no in or out edges will not appear in the
    # schema. Therefore, we remove these unions and their keys from the type equivalence hints.
    return schema, _get_referenced_type_equivalences(graphql_types,
                                                     type_equivalence_hints)
Beispiel #24
0
    async def is_type_of_used_to_resolve_runtime_type_for_union(sync):
        dog_type = GraphQLObjectType(
            "Dog",
            {
                "name": GraphQLField(GraphQLString),
                "woofs": GraphQLField(GraphQLBoolean),
            },
            is_type_of=get_is_type_of(Dog, sync),
        )

        cat_type = GraphQLObjectType(
            "Cat",
            {
                "name": GraphQLField(GraphQLString),
                "meows": GraphQLField(GraphQLBoolean),
            },
            is_type_of=get_is_type_of(Cat, sync),
        )

        pet_type = GraphQLUnionType("Pet", [cat_type, dog_type])

        schema = GraphQLSchema(
            GraphQLObjectType(
                "Query",
                {
                    "pets":
                    GraphQLField(
                        GraphQLList(pet_type),
                        resolve=lambda *_args: [
                            Dog("Odie", True),
                            Cat("Garfield", False),
                        ],
                    )
                },
            ))

        query = """
            {
              pets {
                ... on Dog {
                  name
                  woofs
                }
                ... on Cat {
                  name
                  meows
                }
              }
            }
            """

        assert await execute_query(sync, schema, query) == (
            {
                "pets": [
                    {
                        "name": "Odie",
                        "woofs": True
                    },
                    {
                        "name": "Garfield",
                        "meows": False
                    },
                ]
            },
            None,
        )
Beispiel #25
0
        # type: () -> NullingData
        return NullingData()

    def promiseNest(self):
        # type: () -> Promise
        return resolved(NullingData())

    def nonNullPromiseNest(self):
        # type: () -> Promise
        return resolved(NullingData())


DataType = GraphQLObjectType(
    "DataType",
    lambda: {
        "sync": GraphQLField(GraphQLString),
        "nonNullSync": GraphQLField(GraphQLNonNull(GraphQLString)),
        "promise": GraphQLField(GraphQLString),
        "nonNullPromise": GraphQLField(GraphQLNonNull(GraphQLString)),
        "nest": GraphQLField(DataType),
        "nonNullNest": GraphQLField(GraphQLNonNull(DataType)),
        "promiseNest": GraphQLField(DataType),
        "nonNullPromiseNest": GraphQLField(GraphQLNonNull(DataType)),
    },
)

schema = GraphQLSchema(DataType)


def order_errors(error):
    # type: (Dict[str, Any]) -> Tuple[int, int]
Beispiel #26
0
    async def deprecated_resolve_type_allows_resolving_with_type_object(sync):
        cat_type: GraphQLObjectType
        dog_type: GraphQLObjectType

        pet_type = GraphQLInterfaceType(
            "Pet",
            {"name": GraphQLField(GraphQLString)},
            resolve_type=get_type_resolver(
                lambda: {
                    Dog: dog_type,
                    Cat: cat_type
                }, sync),
        )

        dog_type = GraphQLObjectType(
            "Dog",
            {
                "name": GraphQLField(GraphQLString),
                "woofs": GraphQLField(GraphQLBoolean),
            },
            interfaces=[pet_type],
        )

        cat_type = GraphQLObjectType(
            "Cat",
            {
                "name": GraphQLField(GraphQLString),
                "meows": GraphQLField(GraphQLBoolean),
            },
            interfaces=[pet_type],
        )

        schema = GraphQLSchema(
            GraphQLObjectType(
                "Query",
                {
                    "pets":
                    GraphQLField(
                        GraphQLList(pet_type),
                        resolve=lambda *_args: [
                            Dog("Odie", True),
                            Cat("Garfield", False),
                        ],
                    )
                },
            ),
            types=[cat_type, dog_type],
        )

        query = """
            {
              pets {
                name
                ... on Dog {
                  woofs
                }
                ... on Cat {
                  meows
                }
              }
            }
            """

        assert await execute_query(sync, schema, query) == (
            {
                "pets": [
                    {
                        "name": "Odie",
                        "woofs": True
                    },
                    {
                        "name": "Garfield",
                        "meows": False
                    },
                ]
            },
            None,
        )
    def resolve_type_on_union_yields_useful_error():
        HumanType = GraphQLObjectType("Human",
                                      {"name": GraphQLField(GraphQLString)})

        DogType = GraphQLObjectType(
            "Dog",
            {
                "name": GraphQLField(GraphQLString),
                "woofs": GraphQLField(GraphQLBoolean),
            },
        )

        CatType = GraphQLObjectType(
            "Cat",
            {
                "name": GraphQLField(GraphQLString),
                "meows": GraphQLField(GraphQLBoolean),
            },
        )

        PetType = GraphQLUnionType(
            "Pet",
            [DogType, CatType],
            resolve_type=get_type_resolver({
                Dog: DogType,
                Cat: CatType,
                Human: HumanType
            }),
        )

        schema = GraphQLSchema(
            GraphQLObjectType(
                "Query",
                {
                    "pets":
                    GraphQLField(
                        GraphQLList(PetType),
                        resolve=lambda *_: [
                            Dog("Odie", True),
                            Cat("Garfield", False),
                            Human("Jon"),
                        ],
                    )
                },
            ))

        query = """
            {
              pets {
                ... on Dog {
                  name
                  woofs
                }
                ... on Cat {
                  name
                  meows
                }
              }
            }
            """

        result = graphql_sync(schema, query)
        assert result.data == {
            "pets": [
                {
                    "name": "Odie",
                    "woofs": True
                },
                {
                    "name": "Garfield",
                    "meows": False
                },
                None,
            ]
        }

        assert len(result.errors) == 1
        assert format_error(result.errors[0]) == {
            "message": "Runtime Object type 'Human'"
            " is not a possible type for 'Pet'.",
            "locations": [(3, 15)],
            "path": ["pets", 2],
        }
Beispiel #28
0
    async def resolve_type_can_throw(sync):
        pet_type = GraphQLInterfaceType(
            "Pet",
            {"name": GraphQLField(GraphQLString)},
            resolve_type=get_type_error(sync),
        )

        dog_type = GraphQLObjectType(
            "Dog",
            {
                "name": GraphQLField(GraphQLString),
                "woofs": GraphQLField(GraphQLBoolean),
            },
            interfaces=[pet_type],
        )

        cat_type = GraphQLObjectType(
            "Cat",
            {
                "name": GraphQLField(GraphQLString),
                "meows": GraphQLField(GraphQLBoolean),
            },
            interfaces=[pet_type],
        )

        schema = GraphQLSchema(
            GraphQLObjectType(
                "Query",
                {
                    "pets":
                    GraphQLField(
                        GraphQLList(pet_type),
                        resolve=lambda *_args: [
                            Dog("Odie", True),
                            Cat("Garfield", False),
                        ],
                    )
                },
            ),
            types=[dog_type, cat_type],
        )

        query = """
            {
              pets {
                name
                ... on Dog {
                  woofs
                }
                ... on Cat {
                  meows
                }
              }
            }
            """

        assert await execute_query(sync, schema, query) == (
            {
                "pets": [None, None]
            },
            [
                {
                    "message": "We are testing this error",
                    "locations": [(3, 15)],
                    "path": ["pets", 0],
                },
                {
                    "message": "We are testing this error",
                    "locations": [(3, 15)],
                    "path": ["pets", 1],
                },
            ],
        )
    def is_type_of_used_to_resolve_runtime_type_for_interface():
        PetType = GraphQLInterfaceType("Pet",
                                       {"name": GraphQLField(GraphQLString)})

        DogType = GraphQLObjectType(
            "Dog",
            {
                "name": GraphQLField(GraphQLString),
                "woofs": GraphQLField(GraphQLBoolean),
            },
            interfaces=[PetType],
            is_type_of=get_is_type_of(Dog),
        )

        CatType = GraphQLObjectType(
            "Cat",
            {
                "name": GraphQLField(GraphQLString),
                "meows": GraphQLField(GraphQLBoolean),
            },
            interfaces=[PetType],
            is_type_of=get_is_type_of(Cat),
        )

        schema = GraphQLSchema(
            GraphQLObjectType(
                "Query",
                {
                    "pets":
                    GraphQLField(
                        GraphQLList(PetType),
                        resolve=lambda *_args: [
                            Dog("Odie", True),
                            Cat("Garfield", False),
                        ],
                    )
                },
            ),
            types=[CatType, DogType],
        )

        query = """
            {
              pets {
                name
                ... on Dog {
                  woofs
                }
                ... on Cat {
                  meows
                }
              }
            }
            """

        result = graphql_sync(schema, query)
        assert result == (
            {
                "pets": [
                    {
                        "name": "Odie",
                        "woofs": True
                    },
                    {
                        "name": "Garfield",
                        "meows": False
                    },
                ]
            },
            None,
        )
Beispiel #30
0
    async def executes_arbitrary_code():

        # noinspection PyMethodMayBeStatic,PyMethodMayBeStatic
        class Data:
            def a(self, _info):
                return "Apple"

            def b(self, _info):
                return "Banana"

            def c(self, _info):
                return "Cookie"

            def d(self, _info):
                return "Donut"

            def e(self, _info):
                return "Egg"

            f = "Fish"

            # Called only by DataType::pic static resolver
            def pic(self, _info, size=50):
                return f"Pic of size: {size}"

            def deep(self, _info):
                return DeepData()

            def promise(self, _info):
                return promise_data()

        # noinspection PyMethodMayBeStatic,PyMethodMayBeStatic
        class DeepData:
            def a(self, _info):
                return "Already Been Done"

            def b(self, _info):
                return "Boring"

            def c(self, _info):
                return ["Contrived", None, "Confusing"]

            def deeper(self, _info):
                return [Data(), None, Data()]

        async def promise_data():
            await asyncio.sleep(0)
            return Data()

        DeepDataType: GraphQLObjectType

        DataType = GraphQLObjectType(
            "DataType",
            lambda: {
                "a":
                GraphQLField(GraphQLString),
                "b":
                GraphQLField(GraphQLString),
                "c":
                GraphQLField(GraphQLString),
                "d":
                GraphQLField(GraphQLString),
                "e":
                GraphQLField(GraphQLString),
                "f":
                GraphQLField(GraphQLString),
                "pic":
                GraphQLField(
                    GraphQLString,
                    args={"size": GraphQLArgument(GraphQLInt)},
                    resolve=lambda obj, info, size: obj.pic(info, size),
                ),
                "deep":
                GraphQLField(DeepDataType),
                "promise":
                GraphQLField(DataType),
            },
        )

        DeepDataType = GraphQLObjectType(
            "DeepDataType",
            {
                "a": GraphQLField(GraphQLString),
                "b": GraphQLField(GraphQLString),
                "c": GraphQLField(GraphQLList(GraphQLString)),
                "deeper": GraphQLList(DataType),
            },
        )

        document = parse("""
            query ($size: Int) {
              a,
              b,
              x: c
              ...c
              f
              ...on DataType {
                pic(size: $size)
                promise {
                  a
                }
              }
              deep {
                a
                b
                c
                deeper {
                  a
                  b
                }
              }
            }

            fragment c on DataType {
              d
              e
            }
            """)

        result = await execute(GraphQLSchema(DataType),
                               document,
                               Data(),
                               variable_values={"size": 100})

        assert result == (
            {
                "a": "Apple",
                "b": "Banana",
                "x": "Cookie",
                "d": "Donut",
                "e": "Egg",
                "f": "Fish",
                "pic": "Pic of size: 100",
                "promise": {
                    "a": "Apple"
                },
                "deep": {
                    "a":
                    "Already Been Done",
                    "b":
                    "Boring",
                    "c": ["Contrived", None, "Confusing"],
                    "deeper": [
                        {
                            "a": "Apple",
                            "b": "Banana"
                        },
                        None,
                        {
                            "a": "Apple",
                            "b": "Banana"
                        },
                    ],
                },
            },
            None,
        )