Skip to content

Commit 456fa2c

Browse files
committed
Allow configuration of the ofType introspection depth
1 parent 672281d commit 456fa2c

2 files changed

Lines changed: 33 additions & 37 deletions

File tree

src/graphql/utilities/get_introspection_query.py

Lines changed: 23 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,18 @@ def get_introspection_query(
3636
input_value_deprecation: bool = False,
3737
experimental_directive_deprecation: bool = False,
3838
input_object_one_of: bool = False,
39+
type_depth: int = 9,
3940
) -> str:
4041
"""Get a query for introspection.
4142
4243
Optionally, you can exclude descriptions, include specification URLs,
4344
include repeatability of directives, and specify whether to include
4445
the schema description as well.
46+
47+
The ``type_depth`` argument controls how deep to recurse into nested types.
48+
Larger values will result in more accurate results, but have a higher load
49+
on the server. Some servers might restrict the maximum query depth or
50+
complexity. If that's the case, try decreasing this value. The default is 9.
4551
"""
4652
maybe_description = "description" if descriptions else ""
4753
maybe_specified_by_url = "specifiedByURL" if specified_by_url else ""
@@ -55,6 +61,22 @@ def input_deprecation(string: str) -> Optional[str]:
5561
def directive_deprecation(string: str) -> Optional[str]:
5662
return string if experimental_directive_deprecation else ""
5763

64+
def of_type(level: int, indent: str) -> str:
65+
if level <= 0:
66+
return ""
67+
if level > 100:
68+
msg = (
69+
"Please set type_depth to a reasonable value"
70+
" between 0 and 100; the default is 9."
71+
)
72+
raise ValueError(msg)
73+
return (
74+
f"\n{indent}ofType {{"
75+
f"\n{indent} name"
76+
f"\n{indent} kind{of_type(level - 1, indent + ' ')}"
77+
f"\n{indent}}}"
78+
)
79+
5880
return dedent(f"""
5981
query IntrospectionQuery {{
6082
__schema {{
@@ -125,43 +147,7 @@ def directive_deprecation(string: str) -> Optional[str]:
125147
126148
fragment TypeRef on __Type {{
127149
kind
128-
name
129-
ofType {{
130-
kind
131-
name
132-
ofType {{
133-
kind
134-
name
135-
ofType {{
136-
kind
137-
name
138-
ofType {{
139-
kind
140-
name
141-
ofType {{
142-
kind
143-
name
144-
ofType {{
145-
kind
146-
name
147-
ofType {{
148-
kind
149-
name
150-
ofType {{
151-
kind
152-
name
153-
ofType {{
154-
kind
155-
name
156-
}}
157-
}}
158-
}}
159-
}}
160-
}}
161-
}}
162-
}}
163-
}}
164-
}}
150+
name{of_type(type_depth, " ")}
165151
}}
166152
""")
167153

tests/utilities/test_get_introspection_query.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
from typing import Pattern
44

5+
from pytest import raises
6+
57
from graphql.language import parse
68
from graphql.utilities import build_schema, get_introspection_query
79
from graphql.validation import validate
@@ -118,3 +120,11 @@ def includes_deprecated_input_field_and_args():
118120
ExcpectIntrospectionQuery(input_value_deprecation=False).to_match(
119121
"includeDeprecated: true", 2
120122
)
123+
124+
def throws_error_if_type_depth_is_too_high():
125+
with raises(ValueError) as exc_info:
126+
get_introspection_query(type_depth=101)
127+
assert str(exc_info.value) == (
128+
"Please set type_depth to a reasonable value"
129+
" between 0 and 100; the default is 9."
130+
)

0 commit comments

Comments
 (0)