Пример #1
0
def test_parse_provides_useful_errors():
    with raises(GraphQLSyntaxError) as excinfo:
        parse("""{""")
    assert (
        u'Syntax Error GraphQL (1:2) Expected Name, found EOF\n'
        u'\n'
        u'1: {\n'
        u'    ^\n'
        u''
    ) == excinfo.value.message

    assert excinfo.value.positions == [1]
    assert excinfo.value.locations == [SourceLocation(line=1, column=2)]

    with raises(GraphQLSyntaxError) as excinfo:
        parse("""{ ...MissingOn }
fragment MissingOn Type
""")
    assert 'Syntax Error GraphQL (2:20) Expected "on", found Name "Type"' in str(excinfo.value)

    with raises(GraphQLSyntaxError) as excinfo:
        parse('{ field: {} }')
    assert 'Syntax Error GraphQL (1:10) Expected Name, found {' in str(excinfo.value)

    with raises(GraphQLSyntaxError) as excinfo:
        parse('notanoperation Foo { field }')
    assert 'Syntax Error GraphQL (1:1) Unexpected Name "notanoperation"' in str(excinfo.value)

    with raises(GraphQLSyntaxError) as excinfo:
        parse('...')
    assert 'Syntax Error GraphQL (1:1) Unexpected ...' in str(excinfo.value)
Пример #2
0
def tesst_allows_non_keywords_anywhere_a_name_is_allowed():
    non_keywords = [
        'on',
        'fragment',
        'query',
        'mutation',
        'subscription',
        'true',
        'false'
    ]

    query_template = '''
    query {keyword} {
        ... {fragment_name}
        ... on {keyword} { field }
    }
    fragment {fragment_name} on Type {
        {keyword}({keyword}: ${keyword}) @{keyword}({keyword}: {keyword})
    }
    '''

    for keyword in non_keywords:
        fragment_name = keyword
        if keyword == 'on':
            fragment_name = 'a'

        parse(query_template.format(fragment_name=fragment_name, keyword=keyword))
Пример #3
0
def test_empty_parse():
    with raises(GraphQLSyntaxError) as excinfo:
        parse("")
    assert (
        u'Syntax Error GraphQL (1:1) Unexpected EOF\n'
        u'\n'
    ) == excinfo.value.message
Пример #4
0
def test_visits_in_pararell_allows_for_editing_on_leave():
    visited = []
    ast = parse('{ a, b, c { a, b, c } }', no_location=True)

    class TestVisitor1(Visitor):

        def leave(self, node, key, parent, *args):
            if type(node).__name__ == 'Field' and node.name.value == 'b':
                return REMOVE

    class TestVisitor2(Visitor):

        def enter(self, node, key, parent, *args):
            visited.append(
                ['enter', type(node).__name__, getattr(node, 'value', None)])

        def leave(self, node, key, parent, *args):
            visited.append(
                ['leave', type(node).__name__, getattr(node, 'value', None)])

    edited_ast = visit(ast, ParallelVisitor([TestVisitor1(), TestVisitor2()]))

    assert ast == parse('{ a, b, c { a, b, c } }', no_location=True)
    assert edited_ast == parse('{ a,    c { a,    c } }', no_location=True)

    assert visited == [
        ['enter', 'Document', None],
        ['enter', 'OperationDefinition', None],
        ['enter', 'SelectionSet', None],
        ['enter', 'Field', None],
        ['enter', 'Name', 'a'],
        ['leave', 'Name', 'a'],
        ['leave', 'Field', None],
        ['enter', 'Field', None],
        ['enter', 'Name', 'b'],
        ['leave', 'Name', 'b'],
        ['enter', 'Field', None],
        ['enter', 'Name', 'c'],
        ['leave', 'Name', 'c'],
        ['enter', 'SelectionSet', None],
        ['enter', 'Field', None],
        ['enter', 'Name', 'a'],
        ['leave', 'Name', 'a'],
        ['leave', 'Field', None],
        ['enter', 'Field', None],
        ['enter', 'Name', 'b'],
        ['leave', 'Name', 'b'],
        ['enter', 'Field', None],
        ['enter', 'Name', 'c'],
        ['leave', 'Name', 'c'],
        ['leave', 'Field', None],
        ['leave', 'SelectionSet', None],
        ['leave', 'Field', None],
        ['leave', 'SelectionSet', None],
        ['leave', 'OperationDefinition', None],
        ['leave', 'Document', None]
    ]
Пример #5
0
def test_allows_for_editing_on_enter():
    ast = parse('{ a, b, c { a, b, c } }', no_location=True)

    class TestVisitor(Visitor):

        def enter(self, node, *args):
            if isinstance(node, Field) and node.name.value == 'b':
                return REMOVE

    edited_ast = visit(ast, TestVisitor())

    assert ast == parse('{ a, b, c { a, b, c } }', no_location=True)
    assert edited_ast == parse('{ a,   c { a,   c } }', no_location=True)
Пример #6
0
def test_reraise_from_promise():
    # type: () -> None
    ast = parse("query Example { a }")

    def fail():
        raise Exception("Failed")

    def resolver(context, *_):
        # type: (Optional[Any], *ResolveInfo) -> None
        return Promise(lambda resolve, reject: resolve(fail()))

    Type = GraphQLObjectType(
        "Type", {"a": GraphQLField(GraphQLString, resolver=resolver)})

    result = execute(GraphQLSchema(Type), ast)
    with pytest.raises(Exception) as exc_info:
        result.errors[0].reraise()

    extracted = traceback.extract_tb(exc_info.tb)
    formatted_tb = [row[2:] for row in extracted]
    formatted_tb = [tb for tb in formatted_tb if tb[0] != "reraise"]

    print(formatted_tb)

    assert formatted_tb == [
        ("test_reraise_from_promise", "result.errors[0].reraise()"),
        ("_resolve_from_executor", "executor(resolve, reject)"),
        ("<lambda>",
         "return Promise(lambda resolve, reject: resolve(fail()))"),
        ("fail", 'raise Exception("Failed")'),
    ]

    assert str(exc_info.value) == "Failed"
Пример #7
0
def test_reraise():
    ast = parse('query Example { a }')

    def resolver(context, *_):
        raise Exception('Failed')

    Type = GraphQLObjectType('Type', {
        'a': GraphQLField(GraphQLString, resolver=resolver),
    })

    result = execute(GraphQLSchema(Type), ast)
    with pytest.raises(Exception) as exc_info:
        result.errors[0].reraise()

    extracted = traceback.extract_tb(exc_info.tb)
    formatted_tb = [row[2:] for row in extracted]
    if formatted_tb[2][0] == 'reraise':
        formatted_tb[2:] = formatted_tb[3:]
    
    assert formatted_tb == [
        ('test_reraise', 'result.errors[0].reraise()'),
        ('reraise', 'six.reraise(type(self), self, self.stack)'),
        # ('reraise', 'raise value.with_traceback(tb)'),
        ('resolve_or_error', 'return executor.execute(resolve_fn, source, args, context, info)'),
        ('execute', 'return fn(*args, **kwargs)'), ('resolver', "raise Exception('Failed')")
    ]
    assert str(exc_info.value) == 'Failed'
Пример #8
0
def test_allows_skipping_a_subtree():
    # type: () -> None
    visited = []
    ast = parse("{ a, b { x }, c }")

    class TestVisitor(Visitor):
        def enter(self, node, *args):
            # type: (Any, *Any) -> Optional[Any]
            visited.append(["enter", type(node).__name__, getattr(node, "value", None)])
            if isinstance(node, Field) and node.name.value == "b":
                return False

        def leave(self, node, *args):
            # type: (Union[Field, Name, SelectionSet], *Any) -> None
            visited.append(["leave", type(node).__name__, getattr(node, "value", None)])

    visit(ast, TestVisitor())

    assert visited == [
        ["enter", "Document", None],
        ["enter", "OperationDefinition", None],
        ["enter", "SelectionSet", None],
        ["enter", "Field", None],
        ["enter", "Name", "a"],
        ["leave", "Name", "a"],
        ["leave", "Field", None],
        ["enter", "Field", None],
        ["enter", "Field", None],
        ["enter", "Name", "c"],
        ["leave", "Name", "c"],
        ["leave", "Field", None],
        ["leave", "SelectionSet", None],
        ["leave", "OperationDefinition", None],
        ["leave", "Document", None],
    ]
Пример #9
0
def test_visits_in_pararell_allows_early_exit_while_visiting():
    visited = []
    ast = parse('{ a, b { x }, c }')

    class TestVisitor(Visitor):

        def enter(self, node, key, parent, *args):
            visited.append(
                ['enter', type(node).__name__, getattr(node, 'value', None)])

        def leave(self, node, key, parent, *args):
            visited.append(
                ['leave', type(node).__name__, getattr(node, 'value', None)])
            if type(node).__name__ == 'Name' and node.value == 'x':
                return BREAK

    visit(ast, ParallelVisitor([TestVisitor()]))
    assert visited == [
        ['enter', 'Document', None],
        ['enter', 'OperationDefinition', None],
        ['enter', 'SelectionSet', None],
        ['enter', 'Field', None],
        ['enter', 'Name', 'a'],
        ['leave', 'Name', 'a'],
        ['leave', 'Field', None],
        ['enter', 'Field', None],
        ['enter', 'Name', 'b'],
        ['leave', 'Name', 'b'],
        ['enter', 'SelectionSet', None],
        ['enter', 'Field', None],
        ['enter', 'Name', 'x'],
        ['leave', 'Name', 'x']
    ]
Пример #10
0
def test_visits_in_pararell_allows_skipping_a_subtree():
    visited = []
    ast = parse('{ a, b { x }, c }')

    class TestVisitor(Visitor):

        def enter(self, node, key, parent, *args):
            visited.append(
                ['enter', type(node).__name__, getattr(node, 'value', None)])
            if type(node).__name__ == 'Field' and node.name.value == 'b':
                return False

        def leave(self, node, key, parent, *args):
            visited.append(
                ['leave', type(node).__name__, getattr(node, 'value', None)])

    visit(ast, ParallelVisitor([TestVisitor()]))
    assert visited == [
        ['enter', 'Document', None],
        ['enter', 'OperationDefinition', None],
        ['enter', 'SelectionSet', None],
        ['enter', 'Field', None],
        ['enter', 'Name', 'a'],
        ['leave', 'Name', 'a'],
        ['leave', 'Field', None],
        ['enter', 'Field', None],
        ['enter', 'Field', None],
        ['enter', 'Name', 'c'],
        ['leave', 'Name', 'c'],
        ['leave', 'Field', None],
        ['leave', 'SelectionSet', None],
        ['leave', 'OperationDefinition', None],
        ['leave', 'Document', None],
    ]
Пример #11
0
def test_allows_early_exit_while_visiting():
    visited = []
    ast = parse('{ a, b { x }, c }')

    class TestVisitor(Visitor):

        def enter(self, node, *args):
            visited.append(
                ['enter', type(node).__name__, getattr(node, 'value', None)])
            if isinstance(node, Name) and node.value == 'x':
                return BREAK

        def leave(self, node, *args):
            visited.append(
                ['leave', type(node).__name__, getattr(node, 'value', None)])

    visit(ast, TestVisitor())

    assert visited == [
        ['enter', 'Document', None],
        ['enter', 'OperationDefinition', None],
        ['enter', 'SelectionSet', None],
        ['enter', 'Field', None],
        ['enter', 'Name', 'a'],
        ['leave', 'Name', 'a'],
        ['leave', 'Field', None],
        ['enter', 'Field', None],
        ['enter', 'Name', 'b'],
        ['leave', 'Name', 'b'],
        ['enter', 'SelectionSet', None],
        ['enter', 'Field', None],
        ['enter', 'Name', 'x'],
    ]
Пример #12
0
def test_middleware_class():
    # type: () -> None
    doc = """{
        ok
        not_ok
    }"""

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

        def not_ok(self):
            # type: () -> str
            return "not_ok"

    doc_ast = parse(doc)

    Type = GraphQLObjectType(
        "Type",
        {"ok": GraphQLField(GraphQLString), "not_ok": GraphQLField(GraphQLString)},
    )

    class MyMiddleware(object):
        def resolve(self, next, *args, **kwargs):
            # type: (Callable, *Any, **Any) -> Promise
            p = next(*args, **kwargs)
            return p.then(lambda x: x[::-1])

    middlewares = MiddlewareManager(MyMiddleware())
    result = execute(GraphQLSchema(Type), doc_ast, Data(), middleware=middlewares)
    assert result.data == {"ok": "ko", "not_ok": "ko_ton"}
Пример #13
0
def test_asyncio_py35_executor_return_promise():
    ast = parse('query Example { a, b, c }')

    async def resolver(context, *_):
        await asyncio.sleep(0.001)
        return 'hey'

    async def resolver_2(context, *_):
        await asyncio.sleep(0.003)
        return 'hey2'

    def resolver_3(context, *_):
        return 'hey3'

    Type = GraphQLObjectType(
        'Type', {
            'a': GraphQLField(GraphQLString, resolver=resolver),
            'b': GraphQLField(GraphQLString, resolver=resolver_2),
            'c': GraphQLField(GraphQLString, resolver=resolver_3)
        })

    loop = asyncio.get_event_loop()

    async def do_exec():
        result = await execute(GraphQLSchema(Type),
                               ast,
                               executor=AsyncioExecutor(loop),
                               return_promise=True)
        assert not result.errors
        assert result.data == {'a': 'hey', 'b': 'hey2', 'c': 'hey3'}

    loop.run_until_complete(do_exec())
Пример #14
0
def test_visits_in_pararell_allows_early_exit_while_visiting():
    visited = []
    ast = parse('{ a, b { x }, c }')

    class TestVisitor(Visitor):
        def enter(self, node, key, parent, *args):
            visited.append(
                ['enter',
                 type(node).__name__,
                 getattr(node, 'value', None)])

        def leave(self, node, key, parent, *args):
            visited.append(
                ['leave',
                 type(node).__name__,
                 getattr(node, 'value', None)])
            if type(node).__name__ == 'Name' and node.value == 'x':
                return BREAK

    visit(ast, ParallelVisitor([TestVisitor()]))
    assert visited == [['enter', 'Document', None],
                       ['enter', 'OperationDefinition', None],
                       ['enter', 'SelectionSet', None],
                       ['enter', 'Field', None], ['enter', 'Name', 'a'],
                       ['leave', 'Name', 'a'], ['leave', 'Field', None],
                       ['enter', 'Field', None], ['enter', 'Name', 'b'],
                       ['leave', 'Name', 'b'], ['enter', 'SelectionSet', None],
                       ['enter', 'Field', None], ['enter', 'Name', 'x'],
                       ['leave', 'Name', 'x']]
Пример #15
0
def test_allows_editing_the_root_node_on_enter_and_on_leave():
    ast = parse('{ a, b, c { a, b, c } }', no_location=True)

    definitions = ast.definitions

    class TestVisitor(Visitor):
        def __init__(self):
            self.did_enter = False
            self.did_leave = False

        def enter(self, node, *args):
            if isinstance(node, Document):
                self.did_enter = True
                return Document(loc=node.loc, definitions=[])

        def leave(self, node, *args):
            if isinstance(node, Document):
                self.did_leave = True
                return Document(loc=node.loc, definitions=definitions)

    visitor = TestVisitor()
    edited_ast = visit(ast, visitor)
    assert edited_ast == ast
    assert visitor.did_enter
    assert visitor.did_leave
Пример #16
0
def test_allows_a_named_functions_visitor_api():
    visited = []
    ast = parse('{ a, b { x }, c }')

    class TestVisitor(Visitor):
        def enter_Name(self, node, *args):
            visited.append(
                ['enter',
                 type(node).__name__,
                 getattr(node, 'value', None)])

        def enter_SelectionSet(self, node, *args):
            visited.append(
                ['enter',
                 type(node).__name__,
                 getattr(node, 'value', None)])

        def leave_SelectionSet(self, node, *args):
            visited.append(
                ['leave',
                 type(node).__name__,
                 getattr(node, 'value', None)])

    visit(ast, TestVisitor())

    assert visited == [
        ['enter', 'SelectionSet', None],
        ['enter', 'Name', 'a'],
        ['enter', 'Name', 'b'],
        ['enter', 'SelectionSet', None],
        ['enter', 'Name', 'x'],
        ['leave', 'SelectionSet', None],
        ['enter', 'Name', 'c'],
        ['leave', 'SelectionSet', None],
    ]
Пример #17
0
def test_parses_multi_byte_characters():
    result = parse(u'''
        # This comment has a \u0A0A multi-byte character.
        { field(arg: "Has a \u0A0A multi-byte character.") }
    ''',
                   no_location=True,
                   no_source=True)
    assert result == ast.Document(definitions=[
        ast.OperationDefinition(
            operation='query',
            name=None,
            variable_definitions=None,
            directives=[],
            selection_set=ast.SelectionSet(selections=[
                ast.Field(
                    alias=None,
                    name=ast.Name(value=u'field'),
                    arguments=[
                        ast.Argument(
                            name=ast.
                            Name(value=u'arg'),
                            value=ast
                            .StringValue(
                                value=u'Has a \u0a0a multi-byte character.'))
                    ],
                    directives=[],
                    selection_set=None)
            ]))
    ])
Пример #18
0
def read_operation(src, variables=None, operation_name=None):
    """Reads an operation from the GraphQL document

    Example:

    .. code-block:: python

        op = read_operation('{ foo bar }')
        if op.type is OperationType.QUERY:
            result = engine.execute(query_graph, op.query)

    :param str src: GraphQL document
    :param dict variables: query variables
    :param str operation_name: Name of the operation to execute
    :return: :py:class:`Operation`
    """
    doc = parse(src)
    op = OperationGetter.get(doc, operation_name=operation_name)
    query = GraphQLTransformer.transform(doc, op, variables)
    type_ = OperationType._value2member_map_.get(op.operation)
    name = op.name.value if op.name else None
    if type_ is None:
        raise TypeError('Unsupported operation type: {}'.format(op.operation))
    else:
        return Operation(type_, query, name)
Пример #19
0
def test_asyncio_executor_custom_loop():
    # type: () -> None
    loop = asyncio.get_event_loop()

    def resolver(context, *_):
        # type: (Optional[Any], *ResolveInfo) -> str
        asyncio.sleep(0.001, loop=loop)
        return "hey"

    @asyncio.coroutine
    def resolver_2(context, *_):
        # type: (Optional[Any], *ResolveInfo) -> str
        asyncio.sleep(0.003, loop=loop)
        return "hey2"

    def resolver_3(contest, *_):
        # type: (Optional[Any], *ResolveInfo) -> str
        return "hey3"

    Type = GraphQLObjectType(
        "Type",
        {
            "a": GraphQLField(GraphQLString, resolver=resolver),
            "b": GraphQLField(GraphQLString, resolver=resolver_2),
            "c": GraphQLField(GraphQLString, resolver=resolver_3),
        },
    )

    ast = parse("{ a b c }")
    result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor(loop=loop))
    assert not result.errors
    assert result.data == {"a": "hey", "b": "hey2", "c": "hey3"}
Пример #20
0
def test_asyncio_py35_executor():
    ast = parse("query Example { a, b, c }")

    async def resolver(context, *_):
        await asyncio.sleep(0.001)
        return "hey"

    async def resolver_2(context, *_):
        await asyncio.sleep(0.003)
        return "hey2"

    def resolver_3(context, *_):
        return "hey3"

    Type = GraphQLObjectType(
        "Type",
        {
            "a": GraphQLField(GraphQLString, resolver=resolver),
            "b": GraphQLField(GraphQLString, resolver=resolver_2),
            "c": GraphQLField(GraphQLString, resolver=resolver_3),
        },
    )

    result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor())
    assert not result.errors
    assert result.data == {"a": "hey", "b": "hey2", "c": "hey3"}
Пример #21
0
def test_asyncio_py35_executor_with_error():
    ast = parse('query Example { a, b }')

    async def resolver(context, *_):
        await asyncio.sleep(0.001)
        return 'hey'

    async def resolver_2(context, *_):
        await asyncio.sleep(0.003)
        raise Exception('resolver_2 failed!')

    Type = GraphQLObjectType(
        'Type', {
            'a': GraphQLField(GraphQLString, resolver=resolver),
            'b': GraphQLField(GraphQLString, resolver=resolver_2)
        })

    result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor())
    formatted_errors = list(map(format_error, result.errors))
    assert formatted_errors == [{
        'locations': [{
            'line': 1,
            'column': 20
        }],
        'message': 'resolver_2 failed!'
    }]
    assert result.data == {'a': 'hey', 'b': None}
Пример #22
0
def test_allows_a_named_functions_visitor_api():
    # type: () -> None
    visited = []
    ast = parse("{ a, b { x }, c }")

    class TestVisitor(Visitor):
        def enter_Name(self, node, *args):
            # type: (Name, *Any) -> None
            visited.append(["enter", type(node).__name__, getattr(node, "value", None)])

        def enter_SelectionSet(self, node, *args):
            # type: (SelectionSet, *Any) -> None
            visited.append(["enter", type(node).__name__, getattr(node, "value", None)])

        def leave_SelectionSet(self, node, *args):
            # type: (SelectionSet, *Any) -> None
            visited.append(["leave", type(node).__name__, getattr(node, "value", None)])

    visit(ast, TestVisitor())

    assert visited == [
        ["enter", "SelectionSet", None],
        ["enter", "Name", "a"],
        ["enter", "Name", "b"],
        ["enter", "SelectionSet", None],
        ["enter", "Name", "x"],
        ["leave", "SelectionSet", None],
        ["enter", "Name", "c"],
        ["leave", "SelectionSet", None],
    ]
Пример #23
0
def test_uses_the_subscription_schema_for_subscriptions():
    from rx import Observable
    doc = 'query Q { a } subscription S { a }'

    class Data(object):
        a = 'b'
        c = 'd'

    ast = parse(doc)
    Q = GraphQLObjectType('Q', {'a': GraphQLField(GraphQLString)})
    S = GraphQLObjectType(
        'S', {
            'a':
            GraphQLField(GraphQLString,
                         resolver=lambda root, info: Observable.from_(['b']))
        })
    result = execute(GraphQLSchema(Q, subscription=S),
                     ast,
                     Data(),
                     operation_name='S',
                     allow_subscriptions=True)
    assert isinstance(result, Observable)
    l = []
    result.subscribe(l.append)
    result = l[0]
    assert not result.errors
    assert result.data == {'a': 'b'}
Пример #24
0
def test_allows_a_named_functions_visitor_api():
    visited = []
    ast = parse('{ a, b { x }, c }')

    class TestVisitor(Visitor):

        def enter_Name(self, node, *args):
            visited.append(
                ['enter', type(node).__name__, getattr(node, 'value', None)])

        def enter_SelectionSet(self, node, *args):
            visited.append(
                ['enter', type(node).__name__, getattr(node, 'value', None)])

        def leave_SelectionSet(self, node, *args):
            visited.append(
                ['leave', type(node).__name__, getattr(node, 'value', None)])

    visit(ast, TestVisitor())

    assert visited == [
        ['enter', 'SelectionSet', None],
        ['enter', 'Name', 'a'],
        ['enter', 'Name', 'b'],
        ['enter', 'SelectionSet', None],
        ['enter', 'Name', 'x'],
        ['leave', 'SelectionSet', None],
        ['enter', 'Name', 'c'],
        ['leave', 'SelectionSet', None],
    ]
Пример #25
0
def test_correctly_threads_arguments():
    doc = '''
        query Example {
            b(numArg: 123, stringArg: "foo")
        }
    '''

    def resolver(_, args, *_args):
        assert args['numArg'] == 123
        assert args['stringArg'] == 'foo'
        resolver.got_here = True

    resolver.got_here = False

    doc_ast = parse(doc)

    Type = GraphQLObjectType(
        'Type', {
            'b':
            GraphQLField(GraphQLString,
                         args={
                             'numArg': GraphQLArgument(GraphQLInt),
                             'stringArg': GraphQLArgument(GraphQLString),
                         },
                         resolver=resolver),
        })

    result = execute(GraphQLSchema(Type),
                     doc_ast,
                     None,
                     operation_name='Example')
    assert not result.errors
    assert resolver.got_here
Пример #26
0
def test_nulls_out_error_subtrees():
    doc = '''{
        ok,
        error
    }'''

    class Data(object):

        def ok(self):
            return 'ok'

        def error(self):
            raise Exception('Error getting error')

    doc_ast = parse(doc)

    Type = GraphQLObjectType('Type', {
        'ok': GraphQLField(GraphQLString),
        'error': GraphQLField(GraphQLString),
    })

    result = execute(GraphQLSchema(Type), doc_ast, Data())
    assert result.data == {'ok': 'ok', 'error': None}
    assert len(result.errors) == 1
    assert result.errors[0].message == 'Error getting error'
Пример #27
0
def test_fails_when_an_is_type_of_check_is_not_met():
    class Special(object):
        def __init__(self, value):
            self.value = value

    class NotSpecial(object):
        def __init__(self, value):
            self.value = value

    SpecialType = GraphQLObjectType(
        'SpecialType',
        fields={
            'value': GraphQLField(GraphQLString),
        },
        is_type_of=lambda obj, context, info: isinstance(obj, Special))

    schema = GraphQLSchema(
        GraphQLObjectType(name='Query',
                          fields={
                              'specials':
                              GraphQLField(
                                  GraphQLList(SpecialType),
                                  resolver=lambda root, *_: root['specials'])
                          }))

    query = parse('{ specials { value } }')
    value = {'specials': [Special('foo'), NotSpecial('bar')]}

    result = execute(schema, query, value)

    assert result.data == {'specials': [{'value': 'foo'}, None]}

    assert 'Expected value of type "SpecialType" but got: NotSpecial.' in [
        str(e) for e in result.errors
    ]
Пример #28
0
def test_allows_early_exit_while_visiting():
    # type: () -> None
    visited = []
    ast = parse("{ a, b { x }, c }")

    class TestVisitor(Visitor):
        def enter(self, node, *args):
            # type: (Any, *Any) -> Optional[Any]
            visited.append(["enter", type(node).__name__, getattr(node, "value", None)])
            if isinstance(node, Name) and node.value == "x":
                return BREAK

        def leave(self, node, *args):
            # type: (Union[Field, Name], *Any) -> None
            visited.append(["leave", type(node).__name__, getattr(node, "value", None)])

    visit(ast, TestVisitor())

    assert visited == [
        ["enter", "Document", None],
        ["enter", "OperationDefinition", None],
        ["enter", "SelectionSet", None],
        ["enter", "Field", None],
        ["enter", "Name", "a"],
        ["leave", "Name", "a"],
        ["leave", "Field", None],
        ["enter", "Field", None],
        ["enter", "Name", "b"],
        ["leave", "Name", "b"],
        ["enter", "SelectionSet", None],
        ["enter", "Field", None],
        ["enter", "Name", "x"],
    ]
Пример #29
0
def test_middleware_class():
    doc = '''{
        ok
        not_ok
    }'''

    class Data(object):
        def ok(self):
            return 'ok'

        def not_ok(self):
            return 'not_ok'

    doc_ast = parse(doc)

    Type = GraphQLObjectType('Type', {
        'ok': GraphQLField(GraphQLString),
        'not_ok': GraphQLField(GraphQLString),
    })

    class MyMiddleware(object):
        def resolve(self, next, *args, **kwargs):
            p = next(*args, **kwargs)
            return p.then(lambda x: x[::-1])

    middlewares = MiddlewareManager(MyMiddleware())
    result = execute(GraphQLSchema(Type),
                     doc_ast,
                     Data(),
                     middleware=middlewares)
    assert result.data == {'ok': 'ko', 'not_ok': 'ko_ton'}
def test_asyncio_py35_executor_return_promise():
    ast = parse('query Example { a, b, c }')

    async def resolver(context, *_):
        await asyncio.sleep(0.001)
        return 'hey'

    async def resolver_2(context, *_):
        await asyncio.sleep(0.003)
        return 'hey2'

    def resolver_3(context, *_):
        return 'hey3'

    Type = GraphQLObjectType('Type', {
        'a': GraphQLField(GraphQLString, resolver=resolver),
        'b': GraphQLField(GraphQLString, resolver=resolver_2),
        'c': GraphQLField(GraphQLString, resolver=resolver_3)
    })

    loop = asyncio.get_event_loop()

    async def do_exec():
        result = await execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor(loop), return_promise=True)
        assert not result.errors
        assert result.data == {'a': 'hey', 'b': 'hey2', 'c': 'hey3'}

    loop.run_until_complete(do_exec())
Пример #31
0
def test_threads_root_value_context_correctly():
    # type: () -> None
    doc = "query Example { a }"

    class Data(object):
        context_thing = "thing"

    ast = parse(doc)

    def resolver(root_value, *_):
        # type: (Data, *ResolveInfo) -> None
        assert root_value.context_thing == "thing"
        resolver.got_here = True

    resolver.got_here = False

    Type = GraphQLObjectType(
        "Type", {"a": GraphQLField(GraphQLString, resolver=resolver)})

    result = execute(GraphQLSchema(Type),
                     ast,
                     Data(),
                     operation_name="Example")
    assert not result.errors
    assert resolver.got_here
Пример #32
0
def test_reraise():
    # type: () -> None
    ast = parse("query Example { a }")

    def resolver(context, *_):
        # type: (Optional[Any], *ResolveInfo) -> None
        raise Exception("Failed")

    Type = GraphQLObjectType(
        "Type", {"a": GraphQLField(GraphQLString, resolver=resolver)})

    result = execute(GraphQLSchema(Type), ast)
    with pytest.raises(Exception) as exc_info:
        result.errors[0].reraise()

    extracted = traceback.extract_tb(exc_info.tb)
    formatted_tb = [row[2:] for row in extracted]
    formatted_tb = [tb for tb in formatted_tb if tb[0] != "reraise"]

    assert formatted_tb == [
        ("test_reraise", "result.errors[0].reraise()"),
        (
            "resolve_or_error",
            "return executor.execute(resolve_fn, source, info, **args)",
        ),
        ("execute", "return fn(*args, **kwargs)"),
        ("resolver", 'raise Exception("Failed")'),
    ]

    assert str(exc_info.value) == "Failed"
Пример #33
0
def test_correctly_threads_arguments():
    # type: () -> None
    doc = """
        query Example {
            b(numArg: 123, stringArg: "foo")
        }
    """

    def resolver(source, info, numArg, stringArg):
        # type: (Optional[Any], ResolveInfo, int, str) -> None
        assert numArg == 123
        assert stringArg == "foo"
        resolver.got_here = True

    resolver.got_here = False

    doc_ast = parse(doc)

    Type = GraphQLObjectType(
        "Type",
        {
            "b": GraphQLField(
                GraphQLString,
                args={
                    "numArg": GraphQLArgument(GraphQLInt),
                    "stringArg": GraphQLArgument(GraphQLString),
                },
                resolver=resolver,
            )
        },
    )

    result = execute(GraphQLSchema(Type), doc_ast, None, operation_name="Example")
    assert not result.errors
    assert resolver.got_here
Пример #34
0
def assert_evaluate_mutations_serially(executor=None):
    doc = '''mutation M {
      first: immediatelyChangeTheNumber(newNumber: 1) {
        theNumber
      },
      second: promiseToChangeTheNumber(newNumber: 2) {
        theNumber
      },
      third: immediatelyChangeTheNumber(newNumber: 3) {
        theNumber
      }
      fourth: promiseToChangeTheNumber(newNumber: 4) {
        theNumber
      },
      fifth: immediatelyChangeTheNumber(newNumber: 5) {
        theNumber
      }
    }'''
    ast = parse(doc)
    result = execute(schema,
                     ast,
                     Root(6),
                     operation_name='M',
                     executor=executor)
    assert not result.errors
    assert result.data == \
        {
            'first': {'theNumber': 1},
            'second': {'theNumber': 2},
            'third': {'theNumber': 3},
            'fourth': {'theNumber': 4},
            'fifth': {'theNumber': 5},
        }
Пример #35
0
def test_uses_the_subscription_schema_for_subscriptions():
    # type: () -> None
    from rx import Observable

    doc = "query Q { a } subscription S { a }"

    class Data(object):
        a = "b"
        c = "d"

    ast = parse(doc)
    Q = GraphQLObjectType("Q", {"a": GraphQLField(GraphQLString)})
    S = GraphQLObjectType(
        "S",
        {
            "a": GraphQLField(
                GraphQLString, resolver=lambda root, info: Observable.from_(["b"])
            )
        },
    )
    result = execute(
        GraphQLSchema(Q, subscription=S),
        ast,
        Data(),
        operation_name="S",
        allow_subscriptions=True,
    )
    assert isinstance(result, Observable)
    l = []
    result.subscribe(l.append)
    result = l[0]
    assert not result.errors
    assert result.data == {"a": "b"}
Пример #36
0
def test_asyncio_py35_executor_with_error():
    ast = parse("query Example { a, b }")

    async def resolver(context, *_):
        await asyncio.sleep(0.001)
        return "hey"

    async def resolver_2(context, *_):
        await asyncio.sleep(0.003)
        raise Exception("resolver_2 failed!")

    Type = GraphQLObjectType(
        "Type",
        {
            "a": GraphQLField(GraphQLString, resolver=resolver),
            "b": GraphQLField(GraphQLString, resolver=resolver_2),
        },
    )

    result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor())
    formatted_errors = list(map(format_error, result.errors))
    assert formatted_errors == [
        {
            "locations": [{"line": 1, "column": 20}],
            "path": ["b"],
            "message": "resolver_2 failed!",
        }
    ]
    assert result.data == {"a": "hey", "b": None}
Пример #37
0
def test_gevent_executor():
    def resolver(context, *_):
        gevent.sleep(0.001)
        return "hey"

    def resolver_2(context, *_):
        gevent.sleep(0.003)
        return "hey2"

    def resolver_3(contest, *_):
        return "hey3"

    Type = GraphQLObjectType(
        "Type",
        {
            "a": GraphQLField(GraphQLString, resolver=resolver),
            "b": GraphQLField(GraphQLString, resolver=resolver_2),
            "c": GraphQLField(GraphQLString, resolver=resolver_3),
        },
    )

    ast = parse("{ a b c }")
    result = execute(GraphQLSchema(Type), ast, executor=GeventExecutor())
    assert not result.errors
    assert result.data == {"a": "hey", "b": "hey2", "c": "hey3"}
Пример #38
0
def test_does_not_include_arguments_that_were_not_set():
    # type: () -> None
    schema = GraphQLSchema(
        GraphQLObjectType(
            "Type",
            {
                "field":
                GraphQLField(
                    GraphQLString,
                    resolver=lambda source, info, **args: args and json.dumps(
                        args, sort_keys=True, separators=(",", ":")),
                    args={
                        "a": GraphQLArgument(GraphQLBoolean),
                        "b": GraphQLArgument(GraphQLBoolean),
                        "c": GraphQLArgument(GraphQLBoolean),
                        "d": GraphQLArgument(GraphQLInt),
                        "e": GraphQLArgument(GraphQLInt),
                    },
                )
            },
        ))

    ast = parse("{ field(a: true, c: false, e: 0) }")
    result = execute(schema, ast)
    assert result.data == {"field": '{"a":true,"c":false,"e":0}'}
def test_asyncio_executor_custom_loop():
    loop = asyncio.get_event_loop()

    def resolver(context, *_):
        asyncio.sleep(0.001, loop=loop)
        return 'hey'

    @asyncio.coroutine
    def resolver_2(context, *_):
        asyncio.sleep(0.003, loop=loop)
        return 'hey2'

    def resolver_3(contest, *_):
        return 'hey3'

    Type = GraphQLObjectType(
        'Type', {
            'a': GraphQLField(GraphQLString, resolver=resolver),
            'b': GraphQLField(GraphQLString, resolver=resolver_2),
            'c': GraphQLField(GraphQLString, resolver=resolver_3)
        })

    ast = parse('{ a b c }')
    result = execute(GraphQLSchema(Type),
                     ast,
                     executor=AsyncioExecutor(loop=loop))
    assert not result.errors
    assert result.data == {'a': 'hey', 'b': 'hey2', 'c': 'hey3'}
Пример #40
0
def test_nulls_out_error_subtrees():
    # type: () -> None
    doc = """{
        ok,
        error
    }"""

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

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

    doc_ast = parse(doc)

    Type = GraphQLObjectType(
        "Type",
        {"ok": GraphQLField(GraphQLString), "error": GraphQLField(GraphQLString)},
    )

    result = execute(GraphQLSchema(Type), doc_ast, Data())
    assert result.data == {"ok": "ok", "error": None}
    assert len(result.errors) == 1
    assert result.errors[0].message == "Error getting error"
Пример #41
0
def graphql_to_ir(schema, graphql_string, type_equivalence_hints=None):
    """Convert the given GraphQL string into compiler IR, using the given schema object.

    Args:
        schema: GraphQL schema object, created using the GraphQL library
        graphql_string: string containing the GraphQL to compile to compiler IR
        type_equivalence_hints: optional dict of GraphQL interface or type -> GraphQL union.
                                Used as a workaround for GraphQL's lack of support for
                                inheritance across "types" (i.e. non-interfaces), as well as a
                                workaround for Gremlin's total lack of inheritance-awareness.
                                The key-value pairs in the dict specify that the "key" type
                                is equivalent to the "value" type, i.e. that the GraphQL type or
                                interface in the key is the most-derived common supertype
                                of every GraphQL type in the "value" GraphQL union.
                                Recursive expansion of type equivalence hints is not performed,
                                and only type-level correctness of this argument is enforced.
                                See README.md for more details on everything this parameter does.
                                *****
                                Be very careful with this option, as bad input here will
                                lead to incorrect output queries being generated.
                                *****

    Returns:
        IrAndMetadata named tuple, containing fields:
        - ir_blocks: a list of IR basic block objects
        - input_metadata: a dict of expected input parameters (string) -> inferred GraphQL type
        - output_metadata: a dict of output name (string) -> OutputMetadata object
        - location_types: a dict of location objects -> GraphQL type objects at that location

    Raises flavors of GraphQLError in the following cases:
        - if the query is invalid GraphQL (GraphQLParsingError);
        - if the query doesn't match the schema (GraphQLValidationError);
        - if the query has more than one definition block (GraphQLValidationError);
        - if the query has more than one selection in the root object (GraphQLCompilationError);
        - if the query does not obey directive usage rules (GraphQLCompilationError);
        - if the query provides invalid / disallowed / wrong number of arguments
          for a directive (GraphQLCompilationError).

    In the case of implementation bugs, could also raise ValueError, TypeError, or AssertionError.
    """
    graphql_string = _preprocess_graphql_string(graphql_string)
    try:
        ast = parse(graphql_string)
    except GraphQLSyntaxError as e:
        raise GraphQLParsingError(e)

    validation_errors = _validate_schema_and_ast(schema, ast)

    if validation_errors:
        raise GraphQLValidationError(
            u'String does not validate: {}'.format(validation_errors))

    if len(ast.definitions) != 1:
        raise AssertionError(
            u'Unsupported graphql string with multiple definitions, should have '
            u'been caught in validation: \n{}\n{}'.format(graphql_string, ast))
    base_ast = ast.definitions[0]

    return _compile_root_ast_to_ir(
        schema, base_ast, type_equivalence_hints=type_equivalence_hints)
Пример #42
0
def test_correctly_threads_arguments():
    doc = '''
        query Example {
            b(numArg: 123, stringArg: "foo")
        }
    '''

    def resolver(_, args, *_args):
        assert args['numArg'] == 123
        assert args['stringArg'] == 'foo'
        resolver.got_here = True

    resolver.got_here = False

    doc_ast = parse(doc)

    Type = GraphQLObjectType('Type', {
        'b': GraphQLField(
            GraphQLString,
            args={
                'numArg': GraphQLArgument(GraphQLInt),
                'stringArg': GraphQLArgument(GraphQLString),
            },
            resolver=resolver),
    })

    result = execute(GraphQLSchema(Type), doc_ast, None, operation_name='Example')
    assert not result.errors
    assert resolver.got_here
Пример #43
0
def test_allows_editing_the_root_node_on_enter_and_on_leave():
    ast = parse('{ a, b, c { a, b, c } }', no_location=True)

    definitions = ast.definitions

    class TestVisitor(Visitor):

        def __init__(self):
            self.did_enter = False
            self.did_leave = False

        def enter(self, node, *args):
            if isinstance(node, Document):
                self.did_enter = True
                return Document(
                    loc=node.loc,
                    definitions=[])

        def leave(self, node, *args):
            if isinstance(node, Document):
                self.did_leave = True
                return Document(
                    loc=node.loc,
                    definitions=definitions)

    visitor = TestVisitor()
    edited_ast = visit(ast, visitor)
    assert edited_ast == ast
    assert visitor.did_enter
    assert visitor.did_leave
Пример #44
0
def assert_evaluate_mutations_serially(executor=None):
    doc = '''mutation M {
      first: immediatelyChangeTheNumber(newNumber: 1) {
        theNumber
      },
      second: promiseToChangeTheNumber(newNumber: 2) {
        theNumber
      },
      third: immediatelyChangeTheNumber(newNumber: 3) {
        theNumber
      }
      fourth: promiseToChangeTheNumber(newNumber: 4) {
        theNumber
      },
      fifth: immediatelyChangeTheNumber(newNumber: 5) {
        theNumber
      }
    }'''
    ast = parse(doc)
    result = execute(schema, ast, Root(6), operation_name='M', executor=executor)
    assert not result.errors
    assert result.data == \
        {
            'first': {'theNumber': 1},
            'second': {'theNumber': 2},
            'third': {'theNumber': 3},
            'fourth': {'theNumber': 4},
            'fifth': {'theNumber': 5},
        }
Пример #45
0
def test_middleware_class():
    doc = '''{
        ok
        not_ok
    }'''

    class Data(object):

        def ok(self):
            return 'ok'

        def not_ok(self):
            return 'not_ok'

    doc_ast = parse(doc)

    Type = GraphQLObjectType('Type', {
        'ok': GraphQLField(GraphQLString),
        'not_ok': GraphQLField(GraphQLString),
    })

    class MyMiddleware(object):
        def resolve(self, next, *args, **kwargs):
            p = next(*args, **kwargs)
            return p.then(lambda x: x[::-1])

    middlewares = MiddlewareManager(MyMiddleware())
    result = execute(GraphQLSchema(Type), doc_ast, Data(), middleware=middlewares)
    assert result.data == {'ok': 'ko', 'not_ok': 'ko_ton'}
def test_asyncio_executor_custom_loop():
    loop = asyncio.get_event_loop()

    def resolver(context, *_):
        asyncio.sleep(0.001, loop=loop)
        return 'hey'

    @asyncio.coroutine
    def resolver_2(context, *_):
        asyncio.sleep(0.003, loop=loop)
        return 'hey2'

    def resolver_3(contest, *_):
        return 'hey3'

    Type = GraphQLObjectType('Type', {
        'a': GraphQLField(GraphQLString, resolver=resolver),
        'b': GraphQLField(GraphQLString, resolver=resolver_2),
        'c': GraphQLField(GraphQLString, resolver=resolver_3)
    })

    ast = parse('{ a b c }')
    result = execute(GraphQLSchema(Type), ast, executor=AsyncioExecutor(loop=loop))
    assert not result.errors
    assert result.data == {'a': 'hey', 'b': 'hey2', 'c': 'hey3'}
Пример #47
0
def test_allows_editing_a_node_both_on_enter_and_on_leave():
    ast = parse('{ a, b, c { a, b, c } }', no_location=True)

    class TestVisitor(Visitor):

        def __init__(self):
            self.did_enter = False
            self.did_leave = False

        def enter(self, node, *args):
            if isinstance(node, OperationDefinition):
                self.did_enter = True
                selection_set = node.selection_set
                self.selections = None
                if selection_set:
                    self.selections = selection_set.selections
                new_selection_set = SelectionSet(
                    selections=[])
                return OperationDefinition(
                    name=node.name,
                    variable_definitions=node.variable_definitions,
                    directives=node.directives,
                    loc=node.loc,
                    operation=node.operation,
                    selection_set=new_selection_set)

        def leave(self, node, *args):
            if isinstance(node, OperationDefinition):
                self.did_leave = True
                new_selection_set = None
                if self.selections:
                    new_selection_set = SelectionSet(
                        selections=self.selections)
                return OperationDefinition(
                    name=node.name,
                    variable_definitions=node.variable_definitions,
                    directives=node.directives,
                    loc=node.loc,
                    operation=node.operation,
                    selection_set=new_selection_set)

    visitor = TestVisitor()
    edited_ast = visit(ast, visitor)
    assert ast == parse('{ a, b, c { a, b, c } }', no_location=True)
    assert edited_ast == ast
    assert visitor.did_enter
    assert visitor.did_leave
Пример #48
0
def test_visits_in_pararell_allows_early_exit_from_different_points():
    visited = []
    ast = parse('{ a { y }, b { x } }')

    class TestVisitor(Visitor):

        def __init__(self, name):
            self.name = name

        def enter(self, node, key, parent, *args):
            visited.append(["break-{}".format(self.name), 'enter',
                            type(node).__name__, getattr(node, 'value', None)])

        def leave(self, node, key, parent, *args):
            visited.append(["break-{}".format(self.name), 'leave',
                            type(node).__name__, getattr(node, 'value', None)])
            if type(node).__name__ == 'Field' and node.name.value == self.name:
                return BREAK

    visit(ast, ParallelVisitor([TestVisitor('a'), TestVisitor('b')]))
    assert visited == [
        ['break-a', 'enter', 'Document', None],
        ['break-b', 'enter', 'Document', None],
        ['break-a', 'enter', 'OperationDefinition', None],
        ['break-b', 'enter', 'OperationDefinition', None],
        ['break-a', 'enter', 'SelectionSet', None],
        ['break-b', 'enter', 'SelectionSet', None],
        ['break-a', 'enter', 'Field', None],
        ['break-b', 'enter', 'Field', None],
        ['break-a', 'enter', 'Name', 'a'],
        ['break-b', 'enter', 'Name', 'a'],
        ['break-a', 'leave', 'Name', 'a'],
        ['break-b', 'leave', 'Name', 'a'],
        ['break-a', 'enter', 'SelectionSet', None],
        ['break-b', 'enter', 'SelectionSet', None],
        ['break-a', 'enter', 'Field', None],
        ['break-b', 'enter', 'Field', None],
        ['break-a', 'enter', 'Name', 'y'],
        ['break-b', 'enter', 'Name', 'y'],
        ['break-a', 'leave', 'Name', 'y'],
        ['break-b', 'leave', 'Name', 'y'],
        ['break-a', 'leave', 'Field', None],
        ['break-b', 'leave', 'Field', None],
        ['break-a', 'leave', 'SelectionSet', None],
        ['break-b', 'leave', 'SelectionSet', None],
        ['break-a', 'leave', 'Field', None],
        ['break-b', 'leave', 'Field', None],
        ['break-b', 'enter', 'Field', None],
        ['break-b', 'enter', 'Name', 'b'],
        ['break-b', 'leave', 'Name', 'b'],
        ['break-b', 'enter', 'SelectionSet', None],
        ['break-b', 'enter', 'Field', None],
        ['break-b', 'enter', 'Name', 'x'],
        ['break-b', 'leave', 'Name', 'x'],
        ['break-b', 'leave', 'Field', None],
        ['break-b', 'leave', 'SelectionSet', None],
        ['break-b', 'leave', 'Field', None]
    ]
Пример #49
0
def graphql_to_ir(schema, graphql_string, type_equivalence_hints=None):
    """Convert the given GraphQL string into compiler IR, using the given schema object.

    Args:
        schema: GraphQL schema object, created using the GraphQL library
        graphql_string: string containing the GraphQL to compile to compiler IR
        type_equivalence_hints: optional dict of GraphQL interface or type -> GraphQL union.
                                Used as a workaround for GraphQL's lack of support for
                                inheritance across "types" (i.e. non-interfaces), as well as a
                                workaround for Gremlin's total lack of inheritance-awareness.
                                The key-value pairs in the dict specify that the "key" type
                                is equivalent to the "value" type, i.e. that the GraphQL type or
                                interface in the key is the most-derived common supertype
                                of every GraphQL type in the "value" GraphQL union.
                                Recursive expansion of type equivalence hints is not performed,
                                and only type-level correctness of this argument is enforced.
                                See README.md for more details on everything this parameter does.
                                *****
                                Be very careful with this option, as bad input here will
                                lead to incorrect output queries being generated.
                                *****

    Returns:
        IrAndMetadata named tuple, containing fields:
        - ir_blocks: a list of IR basic block objects
        - input_metadata: a dict of expected input parameters (string) -> inferred GraphQL type
        - output_metadata: a dict of output name (string) -> OutputMetadata object
        - location_types: a dict of location objects -> GraphQL type objects at that location

    Raises flavors of GraphQLError in the following cases:
        - if the query is invalid GraphQL (GraphQLParsingError);
        - if the query doesn't match the schema (GraphQLValidationError);
        - if the query has more than one definition block (GraphQLValidationError);
        - if the query has more than one selection in the root object (GraphQLCompilationError);
        - if the query does not obey directive usage rules (GraphQLCompilationError);
        - if the query provides invalid / disallowed / wrong number of arguments
          for a directive (GraphQLCompilationError).

    In the case of implementation bugs, could also raise ValueError, TypeError, or AssertionError.
    """
    graphql_string = _preprocess_graphql_string(graphql_string)
    try:
        ast = parse(graphql_string)
    except GraphQLSyntaxError as e:
        raise GraphQLParsingError(e)

    validation_errors = _validate_schema_and_ast(schema, ast)

    if validation_errors:
        raise GraphQLValidationError(u'String does not validate: {}'.format(validation_errors))

    if len(ast.definitions) != 1:
        raise AssertionError(u'Unsupported graphql string with multiple definitions, should have '
                             u'been caught in validation: \n{}\n{}'.format(graphql_string, ast))
    base_ast = ast.definitions[0]

    return _compile_root_ast_to_ir(schema, base_ast, type_equivalence_hints=type_equivalence_hints)
Пример #50
0
def test_supports_the_type_root_field():
    TestType = GraphQLObjectType('TestType', {
        'testField': GraphQLField(GraphQLString)
    })
    schema = GraphQLSchema(TestType)
    request = '{ __type(name: "TestType") { name } }'
    result = execute(schema, parse(request), object())
    assert not result.errors
    assert result.data == {'__type': {'name': 'TestType'}}
Пример #51
0
def test_parse_creates_ast():
    source = Source("""{
  node(id: 4) {
    id,
    name
  }
}
""")
    result = parse(source)

    assert result == \
        ast.Document(
            loc=Loc(start=0, end=41, source=source),
            definitions=[ast.OperationDefinition(
                loc=Loc(start=0, end=40, source=source),
                operation='query',
                name=None,
                variable_definitions=None,
                directives=[],
                selection_set=ast.SelectionSet(
                    loc=Loc(start=0, end=40, source=source),
                    selections=[ast.Field(
                        loc=Loc(start=4, end=38, source=source),
                        alias=None,
                        name=ast.Name(
                            loc=Loc(start=4, end=8, source=source),
                            value='node'),
                        arguments=[ast.Argument(
                            name=ast.Name(loc=Loc(start=9, end=11, source=source),
                                          value='id'),
                            value=ast.IntValue(
                                   loc=Loc(start=13, end=14, source=source),
                                   value='4'),
                            loc=Loc(start=9, end=14, source=source))],
                        directives=[],
                        selection_set=ast.SelectionSet(
                            loc=Loc(start=16, end=38, source=source),
                            selections=[ast.Field(
                                loc=Loc(start=22, end=24, source=source),
                                alias=None,
                                name=ast.Name(
                                    loc=Loc(start=22, end=24, source=source),
                                    value='id'),
                                arguments=[],
                                directives=[],
                                selection_set=None),
                                ast.Field(
                                loc=Loc(start=30, end=34, source=source),
                                alias=None,
                                name=ast.Name(
                                    loc=Loc(start=30, end=34, source=source),
                                    value='name'),
                                arguments=[],
                                directives=[],
                                selection_set=None)]))]))])
Пример #52
0
def test_raise():
    ast = parse('query Example { a }')

    def resolver(context, *_):
        raise Exception('Failed')

    Type = GraphQLObjectType('Type', {
        'a': GraphQLField(GraphQLString, resolver=resolver),
    })

    result = execute(GraphQLSchema(Type), ast)
    assert str(result.errors[0]) == 'Failed'
Пример #53
0
def test_does_not_include_illegal_fields_in_output():
    doc = 'mutation M { thisIsIllegalDontIncludeMe }'
    ast = parse(doc)
    Q = GraphQLObjectType('Q', {
        'a': GraphQLField(GraphQLString)
    })
    M = GraphQLObjectType('M', {
        'c': GraphQLField(GraphQLString)
    })
    result = execute(GraphQLSchema(Q, M), ast)
    assert not result.errors
    assert result.data == {}
Пример #54
0
def expect_invalid(schema, rules, query, expected_errors, sort_list=True):
    errors = validate(schema, parse(query), rules)
    assert errors, 'Should not validate'
    for error in expected_errors:
        error['locations'] = [
            {'line': loc.line, 'column': loc.column}
            for loc in error['locations']
        ]
    if sort_list:
        assert sort_lists(list(map(format_error, errors))) == sort_lists(expected_errors)

    else:
        assert list(map(format_error, errors)) == expected_errors
Пример #55
0
def test_raises_if_unknown_operation_name_is_provided():
    doc = 'query Example { a } query OtherExample { a }'

    class Data(object):
        a = 'b'

    ast = parse(doc)
    Type = GraphQLObjectType('Type', {
        'a': GraphQLField(GraphQLString)
    })
    with raises(GraphQLError) as excinfo:
        execute(GraphQLSchema(Type), ast, Data())
    assert 'Must provide operation name if query contains multiple operations.' == str(excinfo.value)
Пример #56
0
def test_raises_if_no_operation_name_is_provided_with_multiple_operations():
    doc = 'query Example { a } query OtherExample { a }'

    class Data(object):
        a = 'b'

    ast = parse(doc)
    Type = GraphQLObjectType('Type', {
        'a': GraphQLField(GraphQLString)
    })
    with raises(GraphQLError) as excinfo:
        execute(GraphQLSchema(Type), ast, Data(), operation_name="UnknownExample")
    assert 'Unknown operation named "UnknownExample".' == str(excinfo.value)
Пример #57
0
def test_raises_if_no_operation_is_provided():
    doc = 'fragment Example on Type { a }'

    class Data(object):
        a = 'b'

    ast = parse(doc)
    Type = GraphQLObjectType('Type', {
        'a': GraphQLField(GraphQLString)
    })
    with raises(GraphQLError) as excinfo:
        execute(GraphQLSchema(Type), ast, Data())
    assert 'Must provide an operation.' == str(excinfo.value)
Пример #58
0
def test_uses_the_named_operation_if_operation_name_is_provided():
    doc = 'query Example { first: a } query OtherExample { second: a }'

    class Data(object):
        a = 'b'

    ast = parse(doc)
    Type = GraphQLObjectType('Type', {
        'a': GraphQLField(GraphQLString)
    })
    result = execute(GraphQLSchema(Type), ast, Data(), operation_name='OtherExample')
    assert not result.errors
    assert result.data == {'second': 'b'}
Пример #59
0
def test_uses_the_only_operation_if_no_operation_name_is_provided():
    doc = 'query Example { a }'

    class Data(object):
        a = 'b'

    ast = parse(doc)
    Type = GraphQLObjectType('Type', {
        'a': GraphQLField(GraphQLString)
    })
    result = execute(GraphQLSchema(Type), ast, Data())
    assert not result.errors
    assert result.data == {'a': 'b'}