Skip to content

Commit 3daa16d

Browse files
committed
Backport VisitorKeyMap type
Replicates graphql/graphql-js@201ed90
1 parent d1ffaef commit 3daa16d

File tree

4 files changed

+31
-28
lines changed

4 files changed

+31
-28
lines changed

src/graphql/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@
182182
ParallelVisitor,
183183
Visitor,
184184
VisitorAction,
185+
VisitorKeyMap,
185186
BREAK,
186187
SKIP,
187188
REMOVE,
@@ -540,6 +541,7 @@
540541
"TypeInfoVisitor",
541542
"Visitor",
542543
"VisitorAction",
544+
"VisitorKeyMap",
543545
"BREAK",
544546
"SKIP",
545547
"REMOVE",

src/graphql/language/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
Visitor,
2424
ParallelVisitor,
2525
VisitorAction,
26+
VisitorKeyMap,
2627
BREAK,
2728
SKIP,
2829
REMOVE,
@@ -117,6 +118,7 @@
117118
"Visitor",
118119
"ParallelVisitor",
119120
"VisitorAction",
121+
"VisitorKeyMap",
120122
"BREAK",
121123
"SKIP",
122124
"REMOVE",

src/graphql/language/visitor.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"Visitor",
2222
"ParallelVisitor",
2323
"VisitorAction",
24+
"VisitorKeyMap",
2425
"visit",
2526
"BREAK",
2627
"SKIP",
@@ -51,8 +52,10 @@ class VisitorActionEnum(Enum):
5152
REMOVE = VisitorActionEnum.REMOVE
5253
IDLE = None
5354

55+
VisitorKeyMap = Dict[str, Tuple[str, ...]]
56+
5457
# Default map from visitor kinds to their traversable node attributes:
55-
QUERY_DOCUMENT_KEYS: Dict[str, Tuple[str, ...]] = {
58+
QUERY_DOCUMENT_KEYS: VisitorKeyMap = {
5659
"name": (),
5760
"document": ("definitions",),
5861
"operation_definition": (
@@ -168,6 +171,9 @@ def leave(self, node, key, parent, path, ancestors):
168171
nodes, you would defined the methods ``enter_field()`` and/or ``leave_field()``,
169172
with the same signature as above. If no kind specific method has been defined
170173
for a given node, the generic method is called.
174+
175+
To customize the node attributes to be used for traversal, you can provide a
176+
dictionary visitor_keys mapping node kinds to node attributes.
171177
"""
172178

173179
# Provide special return values as attributes
@@ -215,9 +221,7 @@ class Stack(NamedTuple):
215221

216222

217223
def visit(
218-
root: Node,
219-
visitor: Visitor,
220-
visitor_keys: Optional[Dict[str, Tuple[str, ...]]] = None,
224+
root: Node, visitor: Visitor, visitor_keys: Optional[VisitorKeyMap] = None
221225
) -> Any:
222226
"""Visit each node in an AST.
223227

tests/language/test_visitor.py

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from copy import copy
22
from functools import partial
3-
from typing import cast, Dict, List, Optional, Tuple
3+
from typing import cast, List, Optional
44

55
from pytest import mark, raises
66

@@ -17,8 +17,8 @@
1717
SKIP,
1818
ParallelVisitor,
1919
Visitor,
20+
VisitorKeyMap,
2021
)
21-
from graphql.language.visitor import QUERY_DOCUMENT_KEYS
2222
from graphql.pyutils import FrozenList
2323

2424
from ..fixtures import kitchen_sink_query # noqa: F401
@@ -1019,13 +1019,14 @@ def leave(node, *_args):
10191019
["leave", "document", None],
10201020
]
10211021

1022-
def does_traverse_unknown_node_with_visitor_keys():
1023-
custom_query_document_keys: Dict[str, Tuple[str, ...]] = {
1024-
**QUERY_DOCUMENT_KEYS,
1025-
"custom_field": ("name", "selection_set"),
1026-
}
1022+
def visits_only_the_specified_kind_in_visitor_key_map():
10271023
visited = []
10281024

1025+
visitor_key_map: VisitorKeyMap = {
1026+
"document": ("definitions",),
1027+
"operation_definition": ("name",),
1028+
}
1029+
10291030
class TestVisitor(Visitor):
10301031
@staticmethod
10311032
def enter(node, *_args):
@@ -1035,26 +1036,20 @@ def enter(node, *_args):
10351036
def leave(node, *_args):
10361037
visited.append(["leave", node.kind, get_value(node)])
10371038

1038-
visit(custom_ast, TestVisitor(), custom_query_document_keys)
1039+
example_document_ast = parse(
1040+
"""
1041+
query ExampleOperation {
1042+
someField
1043+
}
1044+
"""
1045+
)
1046+
1047+
visit(example_document_ast, TestVisitor(), visitor_key_map)
10391048
assert visited == [
10401049
["enter", "document", None],
10411050
["enter", "operation_definition", None],
1042-
["enter", "selection_set", None],
1043-
["enter", "field", None],
1044-
["enter", "name", "a"],
1045-
["leave", "name", "a"],
1046-
["leave", "field", None],
1047-
["enter", "custom_field", None],
1048-
["enter", "name", "b"],
1049-
["leave", "name", "b"],
1050-
["enter", "selection_set", None],
1051-
["enter", "custom_field", None],
1052-
["enter", "name", "c"],
1053-
["leave", "name", "c"],
1054-
["leave", "custom_field", None],
1055-
["leave", "selection_set", None],
1056-
["leave", "custom_field", None],
1057-
["leave", "selection_set", None],
1051+
["enter", "name", "ExampleOperation"],
1052+
["leave", "name", "ExampleOperation"],
10581053
["leave", "operation_definition", None],
10591054
["leave", "document", None],
10601055
]

0 commit comments

Comments
 (0)