Skip to content

Commit ba70d2d

Browse files
authored
Allow graphql-core 3.2.4 by retrofitting introspection commits (#535)
Using gql version of the get_introspection_query method (#523) Adding the input_value_deprecation argument to get_introspection_query_ast (#524) Fix test for introspection type recursion level change in graphql-core v3.3.0a7 (#521) Bump graphql-core to <3.2.5
1 parent 46e188c commit ba70d2d

File tree

5 files changed

+99
-59
lines changed

5 files changed

+99
-59
lines changed

gql/client.py

+11-8
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
GraphQLSchema,
3030
IntrospectionQuery,
3131
build_ast_schema,
32-
get_introspection_query,
3332
parse,
3433
validate,
3534
)
@@ -39,7 +38,7 @@
3938
from .transport.exceptions import TransportClosed, TransportQueryError
4039
from .transport.local_schema import LocalSchemaTransport
4140
from .transport.transport import Transport
42-
from .utilities import build_client_schema
41+
from .utilities import build_client_schema, get_introspection_query_ast
4342
from .utilities import parse_result as parse_result_fn
4443
from .utilities import serialize_variable_values
4544
from .utils import str_first_element
@@ -98,8 +97,8 @@ def __init__(
9897
:param transport: The provided :ref:`transport <Transports>`.
9998
:param fetch_schema_from_transport: Boolean to indicate that if we want to fetch
10099
the schema from the transport using an introspection query.
101-
:param introspection_args: arguments passed to the get_introspection_query
102-
method of graphql-core.
100+
:param introspection_args: arguments passed to the
101+
:meth:`gql.utilities.get_introspection_query_ast` method.
103102
:param execute_timeout: The maximum time in seconds for the execution of a
104103
request before a TimeoutError is raised. Only used for async transports.
105104
Passing None results in waiting forever for a response.
@@ -1289,8 +1288,10 @@ def fetch_schema(self) -> None:
12891288
12901289
Don't use this function and instead set the fetch_schema_from_transport
12911290
attribute to True"""
1292-
introspection_query = get_introspection_query(**self.client.introspection_args)
1293-
execution_result = self.transport.execute(parse(introspection_query))
1291+
introspection_query = get_introspection_query_ast(
1292+
**self.client.introspection_args
1293+
)
1294+
execution_result = self.transport.execute(introspection_query)
12941295

12951296
self.client._build_schema_from_introspection(execution_result)
12961297

@@ -1657,8 +1658,10 @@ async def fetch_schema(self) -> None:
16571658
16581659
Don't use this function and instead set the fetch_schema_from_transport
16591660
attribute to True"""
1660-
introspection_query = get_introspection_query(**self.client.introspection_args)
1661-
execution_result = await self.transport.execute(parse(introspection_query))
1661+
introspection_query = get_introspection_query_ast(
1662+
**self.client.introspection_args
1663+
)
1664+
execution_result = await self.transport.execute(introspection_query)
16621665

16631666
self.client._build_schema_from_introspection(execution_result)
16641667

gql/utilities/get_introspection_query_ast.py

+17-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def get_introspection_query_ast(
1010
specified_by_url: bool = False,
1111
directive_is_repeatable: bool = False,
1212
schema_description: bool = False,
13+
input_value_deprecation: bool = False,
1314
type_recursion_level: int = 7,
1415
) -> DocumentNode:
1516
"""Get a query for introspection as a document using the DSL module.
@@ -43,13 +44,20 @@ def get_introspection_query_ast(
4344

4445
directives = ds.__Schema.directives.select(ds.__Directive.name)
4546

47+
deprecated_expand = {}
48+
49+
if input_value_deprecation:
50+
deprecated_expand = {
51+
"includeDeprecated": True,
52+
}
53+
4654
if descriptions:
4755
directives.select(ds.__Directive.description)
4856
if directive_is_repeatable:
4957
directives.select(ds.__Directive.isRepeatable)
5058
directives.select(
5159
ds.__Directive.locations,
52-
ds.__Directive.args.select(fragment_InputValue),
60+
ds.__Directive.args(**deprecated_expand).select(fragment_InputValue),
5361
)
5462

5563
schema.select(directives)
@@ -69,7 +77,7 @@ def get_introspection_query_ast(
6977
fields.select(ds.__Field.description)
7078

7179
fields.select(
72-
ds.__Field.args.select(fragment_InputValue),
80+
ds.__Field.args(**deprecated_expand).select(fragment_InputValue),
7381
ds.__Field.type.select(fragment_TypeRef),
7482
ds.__Field.isDeprecated,
7583
ds.__Field.deprecationReason,
@@ -89,7 +97,7 @@ def get_introspection_query_ast(
8997

9098
fragment_FullType.select(
9199
fields,
92-
ds.__Type.inputFields.select(fragment_InputValue),
100+
ds.__Type.inputFields(**deprecated_expand).select(fragment_InputValue),
93101
ds.__Type.interfaces.select(fragment_TypeRef),
94102
enum_values,
95103
ds.__Type.possibleTypes.select(fragment_TypeRef),
@@ -105,6 +113,12 @@ def get_introspection_query_ast(
105113
ds.__InputValue.defaultValue,
106114
)
107115

116+
if input_value_deprecation:
117+
fragment_InputValue.select(
118+
ds.__InputValue.isDeprecated,
119+
ds.__InputValue.deprecationReason,
120+
)
121+
108122
fragment_TypeRef.select(
109123
ds.__Type.kind,
110124
ds.__Type.name,

gql/utilities/node_tree.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def _node_tree_recursive(
1919
results.append(" " * indent + f"{type(obj).__name__}")
2020

2121
try:
22-
keys = obj.keys
22+
keys = sorted(obj.keys)
2323
except AttributeError:
2424
# If the object has no keys attribute, print its repr and return.
2525
results.append(" " * (indent + 1) + repr(obj))
@@ -70,6 +70,9 @@ def node_tree(
7070
7171
Useful to debug deep DocumentNode instances created by gql or dsl_gql.
7272
73+
NOTE: from gql version 3.6.0b4 the elements of each node are sorted to ignore
74+
small changes in graphql-core
75+
7376
WARNING: the output of this method is not guaranteed and may change without notice.
7477
"""
7578

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from setuptools import setup, find_packages
44

55
install_requires = [
6-
"graphql-core>=3.2,<3.2.4",
6+
"graphql-core>=3.2,<3.2.5",
77
"yarl>=1.6,<2.0",
88
"backoff>=1.11.1,<3.0",
99
"anyio>=3.0,<5",

tests/starwars/test_dsl.py

+66-46
Original file line numberDiff line numberDiff line change
@@ -984,18 +984,36 @@ def test_get_introspection_query_ast(option):
984984
specified_by_url=option,
985985
directive_is_repeatable=option,
986986
schema_description=option,
987+
input_value_deprecation=option,
987988
)
988989
dsl_introspection_query = get_introspection_query_ast(
989990
descriptions=option,
990991
specified_by_url=option,
991992
directive_is_repeatable=option,
992993
schema_description=option,
994+
input_value_deprecation=option,
993995
)
994996

995-
assert print_ast(gql(introspection_query)) == print_ast(dsl_introspection_query)
996-
assert node_tree(dsl_introspection_query) == node_tree(
997-
gql(print_ast(dsl_introspection_query))
998-
)
997+
try:
998+
assert print_ast(gql(introspection_query)) == print_ast(dsl_introspection_query)
999+
assert node_tree(dsl_introspection_query) == node_tree(
1000+
gql(print_ast(dsl_introspection_query))
1001+
)
1002+
except AssertionError:
1003+
1004+
# From graphql-core version 3.3.0a7, there is two more type recursion levels
1005+
dsl_introspection_query = get_introspection_query_ast(
1006+
descriptions=option,
1007+
specified_by_url=option,
1008+
directive_is_repeatable=option,
1009+
schema_description=option,
1010+
input_value_deprecation=option,
1011+
type_recursion_level=9,
1012+
)
1013+
assert print_ast(gql(introspection_query)) == print_ast(dsl_introspection_query)
1014+
assert node_tree(dsl_introspection_query) == node_tree(
1015+
gql(print_ast(dsl_introspection_query))
1016+
)
9991017

10001018

10011019
def test_typename_aliased(ds):
@@ -1028,11 +1046,10 @@ def test_node_tree_with_loc(ds):
10281046

10291047
node_tree_result = """
10301048
DocumentNode
1031-
loc:
1032-
Location
1033-
<Location 0:43>
10341049
definitions:
10351050
OperationDefinitionNode
1051+
directives:
1052+
empty tuple
10361053
loc:
10371054
Location
10381055
<Location 0:43>
@@ -1043,33 +1060,31 @@ def test_node_tree_with_loc(ds):
10431060
<Location 6:17>
10441061
value:
10451062
'GetHeroName'
1046-
directives:
1047-
empty tuple
1048-
variable_definitions:
1049-
empty tuple
1063+
operation:
1064+
<OperationType.QUERY: 'query'>
10501065
selection_set:
10511066
SelectionSetNode
10521067
loc:
10531068
Location
10541069
<Location 18:43>
10551070
selections:
10561071
FieldNode
1072+
alias:
1073+
None
1074+
arguments:
1075+
empty tuple
1076+
directives:
1077+
empty tuple
10571078
loc:
10581079
Location
10591080
<Location 22:41>
1060-
directives:
1061-
empty tuple
1062-
alias:
1063-
None
10641081
name:
10651082
NameNode
10661083
loc:
10671084
Location
10681085
<Location 22:26>
10691086
value:
10701087
'hero'
1071-
arguments:
1072-
empty tuple
10731088
nullability_assertion:
10741089
None
10751090
selection_set:
@@ -1079,37 +1094,39 @@ def test_node_tree_with_loc(ds):
10791094
<Location 27:41>
10801095
selections:
10811096
FieldNode
1097+
alias:
1098+
None
1099+
arguments:
1100+
empty tuple
1101+
directives:
1102+
empty tuple
10821103
loc:
10831104
Location
10841105
<Location 33:37>
1085-
directives:
1086-
empty tuple
1087-
alias:
1088-
None
10891106
name:
10901107
NameNode
10911108
loc:
10921109
Location
10931110
<Location 33:37>
10941111
value:
10951112
'name'
1096-
arguments:
1097-
empty tuple
10981113
nullability_assertion:
10991114
None
11001115
selection_set:
11011116
None
1102-
operation:
1103-
<OperationType.QUERY: 'query'>
1117+
variable_definitions:
1118+
empty tuple
1119+
loc:
1120+
Location
1121+
<Location 0:43>
11041122
""".strip()
11051123

11061124
node_tree_result_stable = """
11071125
DocumentNode
1108-
loc:
1109-
Location
1110-
<Location 0:43>
11111126
definitions:
11121127
OperationDefinitionNode
1128+
directives:
1129+
empty tuple
11131130
loc:
11141131
Location
11151132
<Location 0:43>
@@ -1120,62 +1137,65 @@ def test_node_tree_with_loc(ds):
11201137
<Location 6:17>
11211138
value:
11221139
'GetHeroName'
1123-
directives:
1124-
empty tuple
1125-
variable_definitions:
1126-
empty tuple
1140+
operation:
1141+
<OperationType.QUERY: 'query'>
11271142
selection_set:
11281143
SelectionSetNode
11291144
loc:
11301145
Location
11311146
<Location 18:43>
11321147
selections:
11331148
FieldNode
1149+
alias:
1150+
None
1151+
arguments:
1152+
empty tuple
1153+
directives:
1154+
empty tuple
11341155
loc:
11351156
Location
11361157
<Location 22:41>
1137-
directives:
1138-
empty tuple
1139-
alias:
1140-
None
11411158
name:
11421159
NameNode
11431160
loc:
11441161
Location
11451162
<Location 22:26>
11461163
value:
11471164
'hero'
1148-
arguments:
1149-
empty tuple
11501165
selection_set:
11511166
SelectionSetNode
11521167
loc:
11531168
Location
11541169
<Location 27:41>
11551170
selections:
11561171
FieldNode
1172+
alias:
1173+
None
1174+
arguments:
1175+
empty tuple
1176+
directives:
1177+
empty tuple
11571178
loc:
11581179
Location
11591180
<Location 33:37>
1160-
directives:
1161-
empty tuple
1162-
alias:
1163-
None
11641181
name:
11651182
NameNode
11661183
loc:
11671184
Location
11681185
<Location 33:37>
11691186
value:
11701187
'name'
1171-
arguments:
1172-
empty tuple
11731188
selection_set:
11741189
None
1175-
operation:
1176-
<OperationType.QUERY: 'query'>
1190+
variable_definitions:
1191+
empty tuple
1192+
loc:
1193+
Location
1194+
<Location 0:43>
11771195
""".strip()
11781196

1197+
print(node_tree(document, ignore_loc=False))
1198+
11791199
try:
11801200
assert node_tree(document, ignore_loc=False) == node_tree_result
11811201
except AssertionError:

0 commit comments

Comments
 (0)