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']]
def test_visits_in_pararell_allows_for_editing_on_enter(): # type: () -> None visited = [] ast = parse("{ a, b, c { a, b, c } }", no_location=True) class TestVisitor1(Visitor): def enter(self, node, key, parent, *args): # type: (Any, Union[None, int, str], Any, *List[Any]) -> Optional[Any] if type(node).__name__ == "Field" and node.name.value == "b": return REMOVE class TestVisitor2(Visitor): def enter(self, node, key, parent, *args): # type: (Any, Union[None, int, str], Any, *List[Any]) -> None visited.append(["enter", type(node).__name__, getattr(node, "value", None)]) def leave( self, node, # type: Union[Field, Name] key, # type: Union[int, str] parent, # type: Union[List[Field], Field] *args # type: List[Any] ): # type: (...) -> None 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", "c"], ["leave", "Name", "c"], ["enter", "SelectionSet", None], ["enter", "Field", None], ["enter", "Name", "a"], ["leave", "Name", "a"], ["leave", "Field", None], ["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], ]
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]]
def test_visits_in_pararell_allows_skipping_a_subtree(): # type: () -> None visited = [] ast = parse("{ a, b { x }, c }") class TestVisitor(Visitor): def enter(self, node, key, parent, *args): # type: (Any, Union[None, int, str], Any, *List[Any]) -> Optional[Any] 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, # type: Union[Field, Name, SelectionSet] key, # type: Union[int, str] parent, # type: Union[List[Field], Field, OperationDefinition] *args # type: List[Any] ): # type: (...) -> None 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], ]
def test_visits_in_pararell_allows_early_exit_while_visiting(): # type: () -> None visited = [] ast = parse("{ a, b { x }, c }") class TestVisitor(Visitor): def enter(self, node, key, parent, *args): # type: (Any, Union[None, int, str], Any, *List[Any]) -> None visited.append( ["enter", type(node).__name__, getattr(node, "value", None)]) def leave( self, node, # type: Union[Field, Name] key, # type: Union[int, str] parent, # type: Union[List[Field], Field] *args # type: List[Any] ): # type: (...) -> Optional[object] 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"], ]
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], ]
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]]
def test_visits_in_pararell_allows_early_exit_from_different_points(): # type: () -> None visited = [] ast = parse("{ a { y }, b { x } }") class TestVisitor(Visitor): def __init__(self, name): # type: (str) -> None self.name = name def enter( self, node, # type: Union[Document, OperationDefinition, SelectionSet] key, # type: Union[None, int, str] parent, # type: Union[List[OperationDefinition], None, OperationDefinition] *args # type: Any ): # type: (...) -> None visited.append( [ "break-{}".format(self.name), "enter", type(node).__name__, getattr(node, "value", None), ] ) def leave( self, node, # type: Union[Field, Name] key, # type: Union[int, str] parent, # type: Union[List[Field], Field] *args # type: List[Any] ): # type: (...) -> Optional[Any] 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], ]