コード例 #1
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],
    ]
コード例 #2
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'],
    ]
コード例 #3
0
ファイル: test_visitor.py プロジェクト: rawls238/graphql-py
def test_allows_skipping_a_subtree():
    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, Field) and node.name.value == 'b':
                return False

        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', 'Field', None ],
        [ 'enter', 'Name', 'c' ],
        [ 'leave', 'Name', 'c' ],
        [ 'leave', 'Field', None ],
        [ 'leave', 'SelectionSet', None ],
        [ 'leave', 'OperationDefinition', None ],
        [ 'leave', 'Document', None ],
    ]
コード例 #4
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']
    ]
コード例 #5
0
ファイル: test_visitor.py プロジェクト: rawls238/graphql-py
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 ],
        ]
コード例 #6
0
def test_allows_skipping_a_subtree():
    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, Field) and node.name.value == 'b':
                return False

        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', 'Field', None],
        ['enter', 'Name', 'c'],
        ['leave', 'Name', 'c'],
        ['leave', 'Field', None],
        ['leave', 'SelectionSet', None],
        ['leave', 'OperationDefinition', None],
        ['leave', 'Document', None],
    ]
コード例 #7
0
ファイル: test_visitor.py プロジェクト: rawls238/graphql-py
def test_visits_edited_node():
    added_field = Field(loc=None,
                        name=Name(loc=None, value='__typename'),
                        alias=None,
                        arguments=None,
                        directives=None,
                        selection_set=None)
    ast = parse('{ a { x } }')

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

        def enter(self, node, *args):
            if isinstance(node, Field) and node.name.value == 'a':
                selection_set = node.selection_set
                selections = []
                if selection_set:
                    selections = selection_set.selections
                new_selection_set = SelectionSet(loc=None, selections=[added_field] + selections)
                return Field(loc=None,
                             name=None,
                             alias=None,
                             arguments=None,
                             directives=None,
                             selection_set=new_selection_set)
            if node is added_field:
                self.did_visit_added_field = True

    visitor = TestVisitor()
    visit(ast, visitor)
    assert visitor.did_visit_added_field
コード例 #8
0
ファイル: test_visitor.py プロジェクト: rawls238/graphql-py
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' ],
        ]
コード例 #9
0
def test_visits_edited_node():
    added_field = Field(loc=None,
                        name=Name(loc=None, value='__typename'),
                        alias=None,
                        arguments=None,
                        directives=None,
                        selection_set=None)
    ast = parse('{ a { x } }')

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

        def enter(self, node, *args):
            if isinstance(node, Field) and node.name.value == 'a':
                selection_set = node.selection_set
                selections = []
                if selection_set:
                    selections = selection_set.selections
                new_selection_set = SelectionSet(loc=None,
                                                 selections=[added_field] +
                                                 selections)
                return Field(loc=None,
                             name=None,
                             alias=None,
                             arguments=None,
                             directives=None,
                             selection_set=new_selection_set)
            if node is added_field:
                self.did_visit_added_field = True

    visitor = TestVisitor()
    visit(ast, visitor)
    assert visitor.did_visit_added_field
コード例 #10
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]
    ]
コード例 #11
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]
    ]
コード例 #12
0
ファイル: test_visitor.py プロジェクト: rawls238/graphql-py
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)
コード例 #13
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)
コード例 #14
0
def test_visits_kitchen_sink():
    visited = []
    ast = parse(KITCHEN_SINK)

    class TestVisitor(Visitor):
        def enter(self, node, key, parent, *args):
            kind = parent and type(parent).__name__
            if kind == 'list':
                kind = None
            visited.append(['enter', type(node).__name__, key, kind])

        def leave(self, node, key, parent, *args):
            kind = parent and type(parent).__name__
            if kind == 'list':
                kind = None
            visited.append(['leave', type(node).__name__, key, kind])

    visit(ast, TestVisitor())

    assert visited == [
        ['enter', 'Document', None, None],
        ['enter', 'OperationDefinition', 0, None],
        ['enter', 'Name', 'name', 'OperationDefinition'],
        ['leave', 'Name', 'name', 'OperationDefinition'],
        ['enter', 'VariableDefinition', 0, None],
        ['enter', 'Variable', 'variable', 'VariableDefinition'],
        ['enter', 'Name', 'name', 'Variable'],
        ['leave', 'Name', 'name', 'Variable'],
        ['leave', 'Variable', 'variable', 'VariableDefinition'],
        ['enter', 'NamedType', 'type', 'VariableDefinition'],
        ['enter', 'Name', 'name', 'NamedType'],
        ['leave', 'Name', 'name', 'NamedType'],
        ['leave', 'NamedType', 'type', 'VariableDefinition'],
        ['leave', 'VariableDefinition', 0, None],
        ['enter', 'VariableDefinition', 1, None],
        ['enter', 'Variable', 'variable', 'VariableDefinition'],
        ['enter', 'Name', 'name', 'Variable'],
        ['leave', 'Name', 'name', 'Variable'],
        ['leave', 'Variable', 'variable', 'VariableDefinition'],
        ['enter', 'NamedType', 'type', 'VariableDefinition'],
        ['enter', 'Name', 'name', 'NamedType'],
        ['leave', 'Name', 'name', 'NamedType'],
        ['leave', 'NamedType', 'type', 'VariableDefinition'],
        ['enter', 'EnumValue', 'default_value', 'VariableDefinition'],
        ['leave', 'EnumValue', 'default_value', 'VariableDefinition'],
        ['leave', 'VariableDefinition', 1, None],
        ['enter', 'SelectionSet', 'selection_set', 'OperationDefinition'],
        ['enter', 'Field', 0, None],
        ['enter', 'Name', 'alias', 'Field'],
        ['leave', 'Name', 'alias', 'Field'],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['enter', 'Argument', 0, None],
        ['enter', 'Name', 'name', 'Argument'],
        ['leave', 'Name', 'name', 'Argument'],
        ['enter', 'ListValue', 'value', 'Argument'],
        ['enter', 'IntValue', 0, None],
        ['leave', 'IntValue', 0, None],
        ['enter', 'IntValue', 1, None],
        ['leave', 'IntValue', 1, None],
        ['leave', 'ListValue', 'value', 'Argument'],
        ['leave', 'Argument', 0, None],
        ['enter', 'SelectionSet', 'selection_set', 'Field'],
        ['enter', 'Field', 0, None],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['leave', 'Field', 0, None],
        ['enter', 'InlineFragment', 1, None],
        ['enter', 'NamedType', 'type_condition', 'InlineFragment'],
        ['enter', 'Name', 'name', 'NamedType'],
        ['leave', 'Name', 'name', 'NamedType'],
        ['leave', 'NamedType', 'type_condition', 'InlineFragment'],
        ['enter', 'Directive', 0, None],
        ['enter', 'Name', 'name', 'Directive'],
        ['leave', 'Name', 'name', 'Directive'],
        ['leave', 'Directive', 0, None],
        ['enter', 'SelectionSet', 'selection_set', 'InlineFragment'],
        ['enter', 'Field', 0, None],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['enter', 'SelectionSet', 'selection_set', 'Field'],
        ['enter', 'Field', 0, None],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['leave', 'Field', 0, None],
        ['enter', 'Field', 1, None],
        ['enter', 'Name', 'alias', 'Field'],
        ['leave', 'Name', 'alias', 'Field'],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['enter', 'Argument', 0, None],
        ['enter', 'Name', 'name', 'Argument'],
        ['leave', 'Name', 'name', 'Argument'],
        ['enter', 'IntValue', 'value', 'Argument'],
        ['leave', 'IntValue', 'value', 'Argument'],
        ['leave', 'Argument', 0, None],
        ['enter', 'Argument', 1, None],
        ['enter', 'Name', 'name', 'Argument'],
        ['leave', 'Name', 'name', 'Argument'],
        ['enter', 'Variable', 'value', 'Argument'],
        ['enter', 'Name', 'name', 'Variable'],
        ['leave', 'Name', 'name', 'Variable'],
        ['leave', 'Variable', 'value', 'Argument'],
        ['leave', 'Argument', 1, None],
        ['enter', 'Directive', 0, None],
        ['enter', 'Name', 'name', 'Directive'],
        ['leave', 'Name', 'name', 'Directive'],
        ['enter', 'Argument', 0, None],
        ['enter', 'Name', 'name', 'Argument'],
        ['leave', 'Name', 'name', 'Argument'],
        ['enter', 'Variable', 'value', 'Argument'],
        ['enter', 'Name', 'name', 'Variable'],
        ['leave', 'Name', 'name', 'Variable'],
        ['leave', 'Variable', 'value', 'Argument'],
        ['leave', 'Argument', 0, None],
        ['leave', 'Directive', 0, None],
        ['enter', 'SelectionSet', 'selection_set', 'Field'],
        ['enter', 'Field', 0, None],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['leave', 'Field', 0, None],
        ['enter', 'FragmentSpread', 1, None],
        ['enter', 'Name', 'name', 'FragmentSpread'],
        ['leave', 'Name', 'name', 'FragmentSpread'],
        ['leave', 'FragmentSpread', 1, None],
        ['leave', 'SelectionSet', 'selection_set', 'Field'],
        ['leave', 'Field', 1, None],
        ['leave', 'SelectionSet', 'selection_set', 'Field'],
        ['leave', 'Field', 0, None],
        ['leave', 'SelectionSet', 'selection_set', 'InlineFragment'],
        ['leave', 'InlineFragment', 1, None],
        ['enter', 'InlineFragment', 2, None],
        ['enter', 'Directive', 0, None],
        ['enter', 'Name', 'name', 'Directive'],
        ['leave', 'Name', 'name', 'Directive'],
        ['enter', 'Argument', 0, None],
        ['enter', 'Name', 'name', 'Argument'],
        ['leave', 'Name', 'name', 'Argument'],
        ['enter', 'Variable', 'value', 'Argument'],
        ['enter', 'Name', 'name', 'Variable'],
        ['leave', 'Name', 'name', 'Variable'],
        ['leave', 'Variable', 'value', 'Argument'],
        ['leave', 'Argument', 0, None],
        ['leave', 'Directive', 0, None],
        ['enter', 'SelectionSet', 'selection_set', 'InlineFragment'],
        ['enter', 'Field', 0, None],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['leave', 'Field', 0, None],
        ['leave', 'SelectionSet', 'selection_set', 'InlineFragment'],
        ['leave', 'InlineFragment', 2, None],
        ['enter', 'InlineFragment', 3, None],
        ['enter', 'SelectionSet', 'selection_set', 'InlineFragment'],
        ['enter', 'Field', 0, None],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['leave', 'Field', 0, None],
        ['leave', 'SelectionSet', 'selection_set', 'InlineFragment'],
        ['leave', 'InlineFragment', 3, None],
        ['leave', 'SelectionSet', 'selection_set', 'Field'],
        ['leave', 'Field', 0, None],
        ['leave', 'SelectionSet', 'selection_set', 'OperationDefinition'],
        ['leave', 'OperationDefinition', 0, None],
        ['enter', 'OperationDefinition', 1, None],
        ['enter', 'Name', 'name', 'OperationDefinition'],
        ['leave', 'Name', 'name', 'OperationDefinition'],
        ['enter', 'SelectionSet', 'selection_set', 'OperationDefinition'],
        ['enter', 'Field', 0, None],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['enter', 'Argument', 0, None],
        ['enter', 'Name', 'name', 'Argument'],
        ['leave', 'Name', 'name', 'Argument'],
        ['enter', 'IntValue', 'value', 'Argument'],
        ['leave', 'IntValue', 'value', 'Argument'],
        ['leave', 'Argument', 0, None],
        ['enter', 'Directive', 0, None],
        ['enter', 'Name', 'name', 'Directive'],
        ['leave', 'Name', 'name', 'Directive'],
        ['leave', 'Directive', 0, None],
        ['enter', 'SelectionSet', 'selection_set', 'Field'],
        ['enter', 'Field', 0, None],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['enter', 'SelectionSet', 'selection_set', 'Field'],
        ['enter', 'Field', 0, None],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['leave', 'Field', 0, None],
        ['leave', 'SelectionSet', 'selection_set', 'Field'],
        ['leave', 'Field', 0, None],
        ['leave', 'SelectionSet', 'selection_set', 'Field'],
        ['leave', 'Field', 0, None],
        ['leave', 'SelectionSet', 'selection_set', 'OperationDefinition'],
        ['leave', 'OperationDefinition', 1, None],
        ['enter', 'FragmentDefinition', 2, None],
        ['enter', 'Name', 'name', 'FragmentDefinition'],
        ['leave', 'Name', 'name', 'FragmentDefinition'],
        ['enter', 'NamedType', 'type_condition', 'FragmentDefinition'],
        ['enter', 'Name', 'name', 'NamedType'],
        ['leave', 'Name', 'name', 'NamedType'],
        ['leave', 'NamedType', 'type_condition', 'FragmentDefinition'],
        ['enter', 'SelectionSet', 'selection_set', 'FragmentDefinition'],
        ['enter', 'Field', 0, None],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['enter', 'Argument', 0, None],
        ['enter', 'Name', 'name', 'Argument'],
        ['leave', 'Name', 'name', 'Argument'],
        ['enter', 'Variable', 'value', 'Argument'],
        ['enter', 'Name', 'name', 'Variable'],
        ['leave', 'Name', 'name', 'Variable'],
        ['leave', 'Variable', 'value', 'Argument'],
        ['leave', 'Argument', 0, None],
        ['enter', 'Argument', 1, None],
        ['enter', 'Name', 'name', 'Argument'],
        ['leave', 'Name', 'name', 'Argument'],
        ['enter', 'Variable', 'value', 'Argument'],
        ['enter', 'Name', 'name', 'Variable'],
        ['leave', 'Name', 'name', 'Variable'],
        ['leave', 'Variable', 'value', 'Argument'],
        ['leave', 'Argument', 1, None],
        ['enter', 'Argument', 2, None],
        ['enter', 'Name', 'name', 'Argument'],
        ['leave', 'Name', 'name', 'Argument'],
        ['enter', 'ObjectValue', 'value', 'Argument'],
        ['enter', 'ObjectField', 0, None],
        ['enter', 'Name', 'name', 'ObjectField'],
        ['leave', 'Name', 'name', 'ObjectField'],
        ['enter', 'StringValue', 'value', 'ObjectField'],
        ['leave', 'StringValue', 'value', 'ObjectField'],
        ['leave', 'ObjectField', 0, None],
        ['leave', 'ObjectValue', 'value', 'Argument'],
        ['leave', 'Argument', 2, None],
        ['leave', 'Field', 0, None],
        ['leave', 'SelectionSet', 'selection_set', 'FragmentDefinition'],
        ['leave', 'FragmentDefinition', 2, None],
        ['enter', 'OperationDefinition', 3, None],
        ['enter', 'SelectionSet', 'selection_set', 'OperationDefinition'],
        ['enter', 'Field', 0, None],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['enter', 'Argument', 0, None],
        ['enter', 'Name', 'name', 'Argument'],
        ['leave', 'Name', 'name', 'Argument'],
        ['enter', 'BooleanValue', 'value', 'Argument'],
        ['leave', 'BooleanValue', 'value', 'Argument'],
        ['leave', 'Argument', 0, None],
        ['enter', 'Argument', 1, None],
        ['enter', 'Name', 'name', 'Argument'],
        ['leave', 'Name', 'name', 'Argument'],
        ['enter', 'BooleanValue', 'value', 'Argument'],
        ['leave', 'BooleanValue', 'value', 'Argument'],
        ['leave', 'Argument', 1, None],
        ['leave', 'Field', 0, None],
        ['enter', 'Field', 1, None],
        ['enter', 'Name', 'name', 'Field'],
        ['leave', 'Name', 'name', 'Field'],
        ['leave', 'Field', 1, None],
        ['leave', 'SelectionSet', 'selection_set', 'OperationDefinition'],
        ['leave', 'OperationDefinition', 3, None],
        ['leave', 'Document', None, None]
    ]
コード例 #15
0
ファイル: test_visitor.py プロジェクト: rawls238/graphql-py
def test_visits_kitchen_sink():
    visited = []
    ast = parse(KITCHEN_SINK)

    class TestVisitor(Visitor):
        def enter(self, node, key, parent, *args):
            kind = parent and type(parent).__name__
            if kind == 'list':
                kind = None
            visited.append(['enter', type(node).__name__, key, kind])

        def leave(self, node, key, parent, *args):
            kind = parent and type(parent).__name__
            if kind == 'list':
                kind = None
            visited.append(['leave', type(node).__name__, key, kind])

    visit(ast, TestVisitor())

    assert visited == [
        [ 'enter', 'Document', None, None ],
        [ 'enter', 'OperationDefinition', 0, None ],
        [ 'enter', 'Name', 'name', 'OperationDefinition' ],
        [ 'leave', 'Name', 'name', 'OperationDefinition' ],
        [ 'enter', 'VariableDefinition', 0, None ],
        [ 'enter', 'Variable', 'variable', 'VariableDefinition' ],
        [ 'enter', 'Name', 'name', 'Variable' ],
        [ 'leave', 'Name', 'name', 'Variable' ],
        [ 'leave', 'Variable', 'variable', 'VariableDefinition' ],
        [ 'enter', 'NamedType', 'type', 'VariableDefinition' ],
        [ 'enter', 'Name', 'name', 'NamedType' ],
        [ 'leave', 'Name', 'name', 'NamedType' ],
        [ 'leave', 'NamedType', 'type', 'VariableDefinition' ],
        [ 'leave', 'VariableDefinition', 0, None ],
        [ 'enter', 'VariableDefinition', 1, None ],
        [ 'enter', 'Variable', 'variable', 'VariableDefinition' ],
        [ 'enter', 'Name', 'name', 'Variable' ],
        [ 'leave', 'Name', 'name', 'Variable' ],
        [ 'leave', 'Variable', 'variable', 'VariableDefinition' ],
        [ 'enter', 'NamedType', 'type', 'VariableDefinition' ],
        [ 'enter', 'Name', 'name', 'NamedType' ],
        [ 'leave', 'Name', 'name', 'NamedType' ],
        [ 'leave', 'NamedType', 'type', 'VariableDefinition' ],
        [ 'enter', 'EnumValue', 'default_value', 'VariableDefinition' ],
        [ 'leave', 'EnumValue', 'default_value', 'VariableDefinition' ],
        [ 'leave', 'VariableDefinition', 1, None ],
        [ 'enter', 'SelectionSet', 'selection_set', 'OperationDefinition' ],
        [ 'enter', 'Field', 0, None ],
        [ 'enter', 'Name', 'alias', 'Field' ],
        [ 'leave', 'Name', 'alias', 'Field' ],
        [ 'enter', 'Name', 'name', 'Field' ],
        [ 'leave', 'Name', 'name', 'Field' ],
        [ 'enter', 'Argument', 0, None ],
        [ 'enter', 'Name', 'name', 'Argument' ],
        [ 'leave', 'Name', 'name', 'Argument' ],
        [ 'enter', 'ListValue', 'value', 'Argument' ],
        [ 'enter', 'IntValue', 0, None ],
        [ 'leave', 'IntValue', 0, None ],
        [ 'enter', 'IntValue', 1, None ],
        [ 'leave', 'IntValue', 1, None ],
        [ 'leave', 'ListValue', 'value', 'Argument' ],
        [ 'leave', 'Argument', 0, None ],
        [ 'enter', 'SelectionSet', 'selection_set', 'Field' ],
        [ 'enter', 'Field', 0, None ],
        [ 'enter', 'Name', 'name', 'Field' ],
        [ 'leave', 'Name', 'name', 'Field' ],
        [ 'leave', 'Field', 0, None ],
        [ 'enter', 'InlineFragment', 1, None ],
        [ 'enter', 'NamedType', 'type_condition', 'InlineFragment' ],
        [ 'enter', 'Name', 'name', 'NamedType' ],
        [ 'leave', 'Name', 'name', 'NamedType' ],
        [ 'leave', 'NamedType', 'type_condition', 'InlineFragment' ],
        [ 'enter', 'Directive', 0, None ],
        [ 'enter', 'Name', 'name', 'Directive' ],
        [ 'leave', 'Name', 'name', 'Directive' ],
        [ 'leave', 'Directive', 0, None ],
        [ 'enter', 'SelectionSet', 'selection_set', 'InlineFragment' ],
        [ 'enter', 'Field', 0, None ],
        [ 'enter', 'Name', 'name', 'Field' ],
        [ 'leave', 'Name', 'name', 'Field' ],
        [ 'enter', 'SelectionSet', 'selection_set', 'Field' ],
        [ 'enter', 'Field', 0, None ],
        [ 'enter', 'Name', 'name', 'Field' ],
        [ 'leave', 'Name', 'name', 'Field' ],
        [ 'leave', 'Field', 0, None ],
        [ 'enter', 'Field', 1, None ],
        [ 'enter', 'Name', 'alias', 'Field' ],
        [ 'leave', 'Name', 'alias', 'Field' ],
        [ 'enter', 'Name', 'name', 'Field' ],
        [ 'leave', 'Name', 'name', 'Field' ],
        [ 'enter', 'Argument', 0, None ],
        [ 'enter', 'Name', 'name', 'Argument' ],
        [ 'leave', 'Name', 'name', 'Argument' ],
        [ 'enter', 'IntValue', 'value', 'Argument' ],
        [ 'leave', 'IntValue', 'value', 'Argument' ],
        [ 'leave', 'Argument', 0, None ],
        [ 'enter', 'Argument', 1, None ],
        [ 'enter', 'Name', 'name', 'Argument' ],
        [ 'leave', 'Name', 'name', 'Argument' ],
        [ 'enter', 'Variable', 'value', 'Argument' ],
        [ 'enter', 'Name', 'name', 'Variable' ],
        [ 'leave', 'Name', 'name', 'Variable' ],
        [ 'leave', 'Variable', 'value', 'Argument' ],
        [ 'leave', 'Argument', 1, None ],
        [ 'enter', 'Directive', 0, None ],
        [ 'enter', 'Name', 'name', 'Directive' ],
        [ 'leave', 'Name', 'name', 'Directive' ],
        [ 'enter', 'Argument', 0, None ],
        [ 'enter', 'Name', 'name', 'Argument' ],
        [ 'leave', 'Name', 'name', 'Argument' ],
        [ 'enter', 'Variable', 'value', 'Argument' ],
        [ 'enter', 'Name', 'name', 'Variable' ],
        [ 'leave', 'Name', 'name', 'Variable' ],
        [ 'leave', 'Variable', 'value', 'Argument' ],
        [ 'leave', 'Argument', 0, None ],
        [ 'leave', 'Directive', 0, None ],
        [ 'enter', 'SelectionSet', 'selection_set', 'Field' ],
        [ 'enter', 'Field', 0, None ],
        [ 'enter', 'Name', 'name', 'Field' ],
        [ 'leave', 'Name', 'name', 'Field' ],
        [ 'leave', 'Field', 0, None ],
        [ 'enter', 'FragmentSpread', 1, None ],
        [ 'enter', 'Name', 'name', 'FragmentSpread' ],
        [ 'leave', 'Name', 'name', 'FragmentSpread' ],
        [ 'leave', 'FragmentSpread', 1, None ],
        [ 'leave', 'SelectionSet', 'selection_set', 'Field' ],
        [ 'leave', 'Field', 1, None ],
        [ 'leave', 'SelectionSet', 'selection_set', 'Field' ],
        [ 'leave', 'Field', 0, None ],
        [ 'leave', 'SelectionSet', 'selection_set', 'InlineFragment' ],
        [ 'leave', 'InlineFragment', 1, None ],
        [ 'leave', 'SelectionSet', 'selection_set', 'Field' ],
        [ 'leave', 'Field', 0, None ],
        [ 'leave', 'SelectionSet', 'selection_set', 'OperationDefinition' ],
        [ 'leave', 'OperationDefinition', 0, None ],
        [ 'enter', 'OperationDefinition', 1, None ],
        [ 'enter', 'Name', 'name', 'OperationDefinition' ],
        [ 'leave', 'Name', 'name', 'OperationDefinition' ],
        [ 'enter', 'SelectionSet', 'selection_set', 'OperationDefinition' ],
        [ 'enter', 'Field', 0, None ],
        [ 'enter', 'Name', 'name', 'Field' ],
        [ 'leave', 'Name', 'name', 'Field' ],
        [ 'enter', 'Argument', 0, None ],
        [ 'enter', 'Name', 'name', 'Argument' ],
        [ 'leave', 'Name', 'name', 'Argument' ],
        [ 'enter', 'IntValue', 'value', 'Argument' ],
        [ 'leave', 'IntValue', 'value', 'Argument' ],
        [ 'leave', 'Argument', 0, None ],
        [ 'enter', 'Directive', 0, None ],
        [ 'enter', 'Name', 'name', 'Directive' ],
        [ 'leave', 'Name', 'name', 'Directive' ],
        [ 'leave', 'Directive', 0, None ],
        [ 'enter', 'SelectionSet', 'selection_set', 'Field' ],
        [ 'enter', 'Field', 0, None ],
        [ 'enter', 'Name', 'name', 'Field' ],
        [ 'leave', 'Name', 'name', 'Field' ],
        [ 'enter', 'SelectionSet', 'selection_set', 'Field' ],
        [ 'enter', 'Field', 0, None ],
        [ 'enter', 'Name', 'name', 'Field' ],
        [ 'leave', 'Name', 'name', 'Field' ],
        [ 'leave', 'Field', 0, None ],
        [ 'leave', 'SelectionSet', 'selection_set', 'Field' ],
        [ 'leave', 'Field', 0, None ],
        [ 'leave', 'SelectionSet', 'selection_set', 'Field' ],
        [ 'leave', 'Field', 0, None ],
        [ 'leave', 'SelectionSet', 'selection_set', 'OperationDefinition' ],
        [ 'leave', 'OperationDefinition', 1, None ],
        [ 'enter', 'FragmentDefinition', 2, None ],
        [ 'enter', 'Name', 'name', 'FragmentDefinition' ],
        [ 'leave', 'Name', 'name', 'FragmentDefinition' ],
        [ 'enter', 'NamedType', 'type_condition', 'FragmentDefinition' ],
        [ 'enter', 'Name', 'name', 'NamedType' ],
        [ 'leave', 'Name', 'name', 'NamedType' ],
        [ 'leave', 'NamedType', 'type_condition', 'FragmentDefinition' ],
        [ 'enter', 'SelectionSet', 'selection_set', 'FragmentDefinition' ],
        [ 'enter', 'Field', 0, None ],
        [ 'enter', 'Name', 'name', 'Field' ],
        [ 'leave', 'Name', 'name', 'Field' ],
        [ 'enter', 'Argument', 0, None ],
        [ 'enter', 'Name', 'name', 'Argument' ],
        [ 'leave', 'Name', 'name', 'Argument' ],
        [ 'enter', 'Variable', 'value', 'Argument' ],
        [ 'enter', 'Name', 'name', 'Variable' ],
        [ 'leave', 'Name', 'name', 'Variable' ],
        [ 'leave', 'Variable', 'value', 'Argument' ],
        [ 'leave', 'Argument', 0, None ],
        [ 'enter', 'Argument', 1, None ],
        [ 'enter', 'Name', 'name', 'Argument' ],
        [ 'leave', 'Name', 'name', 'Argument' ],
        [ 'enter', 'Variable', 'value', 'Argument' ],
        [ 'enter', 'Name', 'name', 'Variable' ],
        [ 'leave', 'Name', 'name', 'Variable' ],
        [ 'leave', 'Variable', 'value', 'Argument' ],
        [ 'leave', 'Argument', 1, None ],
        [ 'enter', 'Argument', 2, None ],
        [ 'enter', 'Name', 'name', 'Argument' ],
        [ 'leave', 'Name', 'name', 'Argument' ],
        [ 'enter', 'ObjectValue', 'value', 'Argument' ],
        [ 'enter', 'ObjectField', 0, None ],
        [ 'enter', 'Name', 'name', 'ObjectField' ],
        [ 'leave', 'Name', 'name', 'ObjectField' ],
        [ 'enter', 'StringValue', 'value', 'ObjectField' ],
        [ 'leave', 'StringValue', 'value', 'ObjectField' ],
        [ 'leave', 'ObjectField', 0, None ],
        [ 'leave', 'ObjectValue', 'value', 'Argument' ],
        [ 'leave', 'Argument', 2, None ],
        [ 'leave', 'Field', 0, None ],
        [ 'leave', 'SelectionSet', 'selection_set', 'FragmentDefinition' ],
        [ 'leave', 'FragmentDefinition', 2, None ],
        [ 'enter', 'OperationDefinition', 3, None ],
        [ 'enter', 'SelectionSet', 'selection_set', 'OperationDefinition' ],
        [ 'enter', 'Field', 0, None ],
        [ 'enter', 'Name', 'name', 'Field' ],
        [ 'leave', 'Name', 'name', 'Field' ],
        [ 'enter', 'Argument', 0, None ],
        [ 'enter', 'Name', 'name', 'Argument' ],
        [ 'leave', 'Name', 'name', 'Argument' ],
        [ 'enter', 'BooleanValue', 'value', 'Argument' ],
        [ 'leave', 'BooleanValue', 'value', 'Argument' ],
        [ 'leave', 'Argument', 0, None ],
        [ 'enter', 'Argument', 1, None ],
        [ 'enter', 'Name', 'name', 'Argument' ],
        [ 'leave', 'Name', 'name', 'Argument' ],
        [ 'enter', 'BooleanValue', 'value', 'Argument' ],
        [ 'leave', 'BooleanValue', 'value', 'Argument' ],
        [ 'leave', 'Argument', 1, None ],
        [ 'leave', 'Field', 0, None ],
        [ 'enter', 'Field', 1, None ],
        [ 'enter', 'Name', 'name', 'Field' ],
        [ 'leave', 'Name', 'name', 'Field' ],
        [ 'leave', 'Field', 1, None ],
        [ 'leave', 'SelectionSet', 'selection_set', 'OperationDefinition' ],
        [ 'leave', 'OperationDefinition', 3, None ],
        [ 'leave', 'Document', None, None ]
    ]
コード例 #16
0
def test_visits_with_typeinfo_maintains_type_info_during_edit():
    visited = []
    ast = parse('{ human(id: 4) { name, pets }, alien }')

    type_info = TypeInfo(test_schema)

    class TestVisitor(Visitor):

        def enter(self, node, key, parent, *args):
            parent_type = type_info.get_parent_type()
            _type = type_info.get_type()
            input_type = type_info.get_input_type()
            visited.append([
                'enter',
                type(node).__name__,
                node.value if type(node).__name__ == "Name" else None,
                str(parent_type) if parent_type else None,
                str(_type) if _type else None,
                str(input_type) if input_type else None
            ])

            # Make a query valid by adding missing selection sets.
            if type(node).__name__ == "Field" and not node.selection_set and is_composite_type(get_named_type(_type)):
                return Field(
                    alias=node.alias,
                    name=node.name,
                    arguments=node.arguments,
                    directives=node.directives,
                    selection_set=SelectionSet(
                        [Field(name=Name(value='__typename'))]
                    )
                )

        def leave(self, node, key, parent, *args):
            parent_type = type_info.get_parent_type()
            _type = type_info.get_type()
            input_type = type_info.get_input_type()
            visited.append([
                'leave',
                type(node).__name__,
                node.value if type(node).__name__ == "Name" else None,
                str(parent_type) if parent_type else None,
                str(_type) if _type else None,
                str(input_type) if input_type else None
            ])

    edited_ast = visit(ast, TypeInfoVisitor(type_info, TestVisitor()))

    # assert print_ast(ast) == print_ast(parse(
    #     '{ human(id: 4) { name, pets }, alien }'
    # ))
    assert print_ast(edited_ast) == print_ast(parse(
        '{ human(id: 4) { name, pets { __typename } }, alien { __typename } }'
    ))
    assert visited == [
        ['enter', 'Document', None, None, None, None],
        ['enter', 'OperationDefinition', None, None, 'QueryRoot', None],
        ['enter', 'SelectionSet', None, 'QueryRoot', 'QueryRoot', None],
        ['enter', 'Field', None, 'QueryRoot', 'Human', None],
        ['enter', 'Name', 'human', 'QueryRoot', 'Human', None],
        ['leave', 'Name', 'human', 'QueryRoot', 'Human', None],
        ['enter', 'Argument', None, 'QueryRoot', 'Human', 'ID'],
        ['enter', 'Name', 'id', 'QueryRoot', 'Human', 'ID'],
        ['leave', 'Name', 'id', 'QueryRoot', 'Human', 'ID'],
        ['enter', 'IntValue', None, 'QueryRoot', 'Human', 'ID'],
        ['leave', 'IntValue', None, 'QueryRoot', 'Human', 'ID'],
        ['leave', 'Argument', None, 'QueryRoot', 'Human', 'ID'],
        ['enter', 'SelectionSet', None, 'Human', 'Human', None],
        ['enter', 'Field', None, 'Human', 'String', None],
        ['enter', 'Name', 'name', 'Human', 'String', None],
        ['leave', 'Name', 'name', 'Human', 'String', None],
        ['leave', 'Field', None, 'Human', 'String', None],
        ['enter', 'Field', None, 'Human', '[Pet]', None],
        ['enter', 'Name', 'pets', 'Human', '[Pet]', None],
        ['leave', 'Name', 'pets', 'Human', '[Pet]', None],
        ['enter', 'SelectionSet', None, 'Pet', '[Pet]', None],
        ['enter', 'Field', None, 'Pet', 'String!', None],
        ['enter', 'Name', '__typename', 'Pet', 'String!', None],
        ['leave', 'Name', '__typename', 'Pet', 'String!', None],
        ['leave', 'Field', None, 'Pet', 'String!', None],
        ['leave', 'SelectionSet', None, 'Pet', '[Pet]', None],
        ['leave', 'Field', None, 'Human', '[Pet]', None],
        ['leave', 'SelectionSet', None, 'Human', 'Human', None],
        ['leave', 'Field', None, 'QueryRoot', 'Human', None],
        ['enter', 'Field', None, 'QueryRoot', 'Alien', None],
        ['enter', 'Name', 'alien', 'QueryRoot', 'Alien', None],
        ['leave', 'Name', 'alien', 'QueryRoot', 'Alien', None],
        ['enter', 'SelectionSet', None, 'Alien', 'Alien', None],
        ['enter', 'Field', None, 'Alien', 'String!', None],
        ['enter', 'Name', '__typename', 'Alien', 'String!', None],
        ['leave', 'Name', '__typename', 'Alien', 'String!', None],
        ['leave', 'Field', None, 'Alien', 'String!', None],
        ['leave', 'SelectionSet', None, 'Alien', 'Alien', None],
        ['leave', 'Field', None, 'QueryRoot', 'Alien', None],
        ['leave', 'SelectionSet', None, 'QueryRoot', 'QueryRoot', None],
        ['leave', 'OperationDefinition', None, None, 'QueryRoot', None],
        ['leave', 'Document', None, None, None, None]
    ]
コード例 #17
0
ファイル: graphql.py プロジェクト: vharitonsky/hiku
 def transform(cls, document):
     visitor = cls()
     visit(document, visitor)
     return visitor._stack[0]
コード例 #18
0
 def transform(cls, document):
     visitor = cls()
     visit(document, visitor)
     return visitor._stack[0]
コード例 #19
0
def test_visits_with_typeinfo_maintains_type_info_during_visit():
    visited = []
    ast = parse('{ human(id: 4) { name, pets { name }, unknown } }')

    type_info = TypeInfo(test_schema)

    class TestVisitor(Visitor):

        def enter(self, node, key, parent, *args):
            parent_type = type_info.get_parent_type()
            _type = type_info.get_type()
            input_type = type_info.get_input_type()
            visited.append([
                'enter',
                type(node).__name__,
                node.value if type(node).__name__ == "Name" else None,
                str(parent_type) if parent_type else None,
                str(_type) if _type else None,
                str(input_type) if input_type else None
            ])

        def leave(self, node, key, parent, *args):
            parent_type = type_info.get_parent_type()
            _type = type_info.get_type()
            input_type = type_info.get_input_type()
            visited.append([
                'leave',
                type(node).__name__,
                node.value if type(node).__name__ == "Name" else None,
                str(parent_type) if parent_type else None,
                str(_type) if _type else None,
                str(input_type) if input_type else None
            ])

    visit(ast, TypeInfoVisitor(type_info, TestVisitor()))
    assert visited == [
        ['enter', 'Document', None, None, None, None],
        ['enter', 'OperationDefinition', None, None, 'QueryRoot', None],
        ['enter', 'SelectionSet', None, 'QueryRoot', 'QueryRoot', None],
        ['enter', 'Field', None, 'QueryRoot', 'Human', None],
        ['enter', 'Name', 'human', 'QueryRoot', 'Human', None],
        ['leave', 'Name', 'human', 'QueryRoot', 'Human', None],
        ['enter', 'Argument', None, 'QueryRoot', 'Human', 'ID'],
        ['enter', 'Name', 'id', 'QueryRoot', 'Human', 'ID'],
        ['leave', 'Name', 'id', 'QueryRoot', 'Human', 'ID'],
        ['enter', 'IntValue', None, 'QueryRoot', 'Human', 'ID'],
        ['leave', 'IntValue', None, 'QueryRoot', 'Human', 'ID'],
        ['leave', 'Argument', None, 'QueryRoot', 'Human', 'ID'],
        ['enter', 'SelectionSet', None, 'Human', 'Human', None],
        ['enter', 'Field', None, 'Human', 'String', None],
        ['enter', 'Name', 'name', 'Human', 'String', None],
        ['leave', 'Name', 'name', 'Human', 'String', None],
        ['leave', 'Field', None, 'Human', 'String', None],
        ['enter', 'Field', None, 'Human', '[Pet]', None],
        ['enter', 'Name', 'pets', 'Human', '[Pet]', None],
        ['leave', 'Name', 'pets', 'Human', '[Pet]', None],
        ['enter', 'SelectionSet', None, 'Pet', '[Pet]', None],
        ['enter', 'Field', None, 'Pet', 'String', None],
        ['enter', 'Name', 'name', 'Pet', 'String', None],
        ['leave', 'Name', 'name', 'Pet', 'String', None],
        ['leave', 'Field', None, 'Pet', 'String', None],
        ['leave', 'SelectionSet', None, 'Pet', '[Pet]', None],
        ['leave', 'Field', None, 'Human', '[Pet]', None],
        ['enter', 'Field', None, 'Human', None, None],
        ['enter', 'Name', 'unknown', 'Human', None, None],
        ['leave', 'Name', 'unknown', 'Human', None, None],
        ['leave', 'Field', None, 'Human', None, None],
        ['leave', 'SelectionSet', None, 'Human', 'Human', None],
        ['leave', 'Field', None, 'QueryRoot', 'Human', None],
        ['leave', 'SelectionSet', None, 'QueryRoot', 'QueryRoot', None],
        ['leave', 'OperationDefinition', None, None, 'QueryRoot', None],
        ['leave', 'Document', None, None, None, None]
    ]