Skip to content

Commit c445f3a

Browse files
committed
Using GraphQLRequest instead of DocumentNode for gql, execute, and subscribe methods
1 parent b221c0e commit c445f3a

22 files changed

+341
-367
lines changed

gql/client.py

Lines changed: 71 additions & 165 deletions
Large diffs are not rendered by default.

gql/dsl.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
)
6565
from graphql.pyutils import inspect
6666

67+
from .graphql_request import GraphQLRequest
6768
from .utils import to_camel_case
6869

6970
log = logging.getLogger(__name__)
@@ -214,7 +215,7 @@ def ast_from_value(value: Any, type_: GraphQLInputType) -> Optional[ValueNode]:
214215

215216
def dsl_gql(
216217
*operations: "DSLExecutable", **operations_with_name: "DSLExecutable"
217-
) -> DocumentNode:
218+
) -> GraphQLRequest:
218219
r"""Given arguments instances of :class:`DSLExecutable`
219220
containing GraphQL operations or fragments,
220221
generate a Document which can be executed later in a
@@ -231,7 +232,8 @@ def dsl_gql(
231232
:param \**operations_with_name: the GraphQL operations with an operation name
232233
:type \**operations_with_name: DSLQuery, DSLMutation, DSLSubscription
233234
234-
:return: a Document which can be later executed or subscribed by a
235+
:return: a :class:`GraphQLRequest <gql.GraphQLRequest>`
236+
which can be later executed or subscribed by a
235237
:class:`Client <gql.client.Client>`, by an
236238
:class:`async session <gql.client.AsyncClientSession>` or by a
237239
:class:`sync session <gql.client.SyncClientSession>`
@@ -259,10 +261,12 @@ def dsl_gql(
259261
f"Received: {type(operation)}."
260262
)
261263

262-
return DocumentNode(
264+
document = DocumentNode(
263265
definitions=[operation.executable_ast for operation in all_operations]
264266
)
265267

268+
return GraphQLRequest(document)
269+
266270

267271
class DSLSchema:
268272
"""The DSLSchema is the root of the DSL code.

gql/gql.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,17 @@
1-
from __future__ import annotations
1+
from .graphql_request import GraphQLRequest
22

3-
from graphql import DocumentNode, Source, parse
43

5-
6-
def gql(request_string: str | Source) -> DocumentNode:
7-
"""Given a string containing a GraphQL request, parse it into a Document.
4+
def gql(request_string: str) -> GraphQLRequest:
5+
"""Given a string containing a GraphQL request,
6+
parse it into a Document and put it into a GraphQLRequest object
87
98
:param request_string: the GraphQL request as a String
10-
:type request_string: str | Source
11-
:return: a Document which can be later executed or subscribed by a
9+
:return: a :class:`GraphQLRequest <gql.GraphQLRequest>`
10+
which can be later executed or subscribed by a
1211
:class:`Client <gql.client.Client>`, by an
1312
:class:`async session <gql.client.AsyncClientSession>` or by a
1413
:class:`sync session <gql.client.SyncClientSession>`
1514
1615
:raises graphql.error.GraphQLError: if a syntax error is encountered.
1716
"""
18-
if isinstance(request_string, Source):
19-
source = request_string
20-
elif isinstance(request_string, str):
21-
source = Source(request_string, "GraphQL request")
22-
else:
23-
raise TypeError("Request must be passed as a string or Source object.")
24-
return parse(source)
17+
return GraphQLRequest(request_string)

gql/graphql_request.py

Lines changed: 86 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,68 @@
1+
import warnings
12
from typing import Any, Dict, Optional, Union
23

3-
from graphql import DocumentNode, GraphQLSchema, print_ast
4-
5-
from .gql import gql
6-
from .utilities import serialize_variable_values
4+
from graphql import DocumentNode, GraphQLSchema, Source, parse, print_ast
75

86

97
class GraphQLRequest:
108
"""GraphQL Request to be executed."""
119

1210
def __init__(
1311
self,
14-
document: Union[DocumentNode, str],
12+
request: Union[DocumentNode, "GraphQLRequest", str],
1513
*,
1614
variable_values: Optional[Dict[str, Any]] = None,
1715
operation_name: Optional[str] = None,
1816
):
1917
"""
2018
Initialize a GraphQL request.
2119
22-
Args:
23-
document: GraphQL query as AST Node object or as a string.
24-
If string, it will be converted to DocumentNode using gql().
25-
variable_values: Dictionary of input parameters (Default: None).
26-
operation_name: Name of the operation that shall be executed.
27-
Only required in multi-operation documents (Default: None).
20+
:param request: GraphQL request as DocumentNode object or as a string.
21+
If string, it will be converted to DocumentNode.
22+
:param variable_values: Dictionary of input parameters (Default: None).
23+
:param operation_name: Name of the operation that shall be executed.
24+
Only required in multi-operation documents (Default: None).
25+
26+
:return: a :class:`GraphQLRequest <gql.GraphQLRequest>`
27+
which can be later executed or subscribed by a
28+
:class:`Client <gql.client.Client>`, by an
29+
:class:`async session <gql.client.AsyncClientSession>` or by a
30+
:class:`sync session <gql.client.SyncClientSession>`
31+
:raises graphql.error.GraphQLError: if a syntax error is encountered.
32+
2833
"""
29-
if isinstance(document, str):
30-
self.document = gql(document)
31-
else:
32-
self.document = document
34+
if isinstance(request, str):
35+
source = Source(request, "GraphQL request")
36+
self.document = parse(source)
37+
elif isinstance(request, DocumentNode):
38+
self.document = request
39+
elif not isinstance(request, GraphQLRequest):
40+
raise TypeError(f"Unexpected type for GraphQLRequest: {type(request)}")
3341

34-
self.variable_values = variable_values
35-
self.operation_name = operation_name
42+
if isinstance(request, GraphQLRequest):
43+
self.document = request.document
44+
self.variable_values: Optional[Dict[str, Any]] = (
45+
request.variable_values
46+
if request.variable_values is not None
47+
else variable_values
48+
)
49+
self.operation_name: Optional[str] = (
50+
request.operation_name
51+
if request.operation_name is not None
52+
else operation_name
53+
)
54+
else:
55+
self.variable_values = variable_values
56+
self.operation_name = operation_name
3657

3758
def serialize_variable_values(self, schema: GraphQLSchema) -> "GraphQLRequest":
59+
60+
from .utilities.serialize_variable_values import serialize_variable_values
61+
3862
assert self.variable_values
3963

4064
return GraphQLRequest(
41-
document=self.document,
65+
self.document,
4266
variable_values=serialize_variable_values(
4367
schema=schema,
4468
document=self.document,
@@ -63,3 +87,47 @@ def payload(self) -> Dict[str, Any]:
6387

6488
def __str__(self):
6589
return str(self.payload)
90+
91+
92+
def support_deprecated_request(
93+
request: Union[GraphQLRequest, DocumentNode],
94+
kwargs: Dict,
95+
) -> GraphQLRequest:
96+
"""This methods is there temporarily to convert the old style of calling
97+
execute and subscribe methods with a DocumentNode,
98+
variable_values and operation_name arguments.
99+
"""
100+
101+
if isinstance(request, DocumentNode):
102+
warnings.warn(
103+
(
104+
"Using a DocumentNode is deprecated. Please use a "
105+
"GraphQLRequest instead."
106+
),
107+
DeprecationWarning,
108+
stacklevel=2,
109+
)
110+
request = GraphQLRequest(request)
111+
112+
if not isinstance(request, GraphQLRequest):
113+
raise TypeError("request should be a GraphQLRequest object")
114+
115+
variable_values = kwargs.pop("variable_values", None)
116+
operation_name = kwargs.pop("operation_name", None)
117+
118+
if variable_values or operation_name:
119+
warnings.warn(
120+
(
121+
"Using variable_values and operation_name arguments of "
122+
"execute and subscribe methods is deprecated. Instead, "
123+
"please use the variable_values and operation_name properties "
124+
"of GraphQLRequest"
125+
),
126+
DeprecationWarning,
127+
stacklevel=2,
128+
)
129+
130+
request.variable_values = variable_values
131+
request.operation_name = operation_name
132+
133+
return request

gql/utilities/get_introspection_query_ast.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,4 @@ def get_introspection_query_ast(
139139

140140
dsl_query = dsl_gql(query, fragment_FullType, fragment_InputValue, fragment_TypeRef)
141141

142-
return dsl_query
142+
return dsl_query.document

tests/custom_scalars/test_money.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -765,14 +765,14 @@ async def test_custom_scalar_serialize_variables_sync_transport_2(
765765
def test_code():
766766
with Client(schema=schema, transport=transport, parse_results=True) as session:
767767

768-
query = gql("query myquery($money: Money) {toEuros(money: $money)}")
768+
query = "query myquery($money: Money) {toEuros(money: $money)}"
769769

770770
variable_values = {"money": Money(10, "DM")}
771771

772772
results = session.execute_batch(
773773
[
774-
GraphQLRequest(document=query, variable_values=variable_values),
775-
GraphQLRequest(document=query, variable_values=variable_values),
774+
GraphQLRequest(query, variable_values=variable_values),
775+
GraphQLRequest(query, variable_values=variable_values),
776776
],
777777
serialize_variables=True,
778778
)
@@ -793,14 +793,14 @@ async def test_custom_scalar_serialize_variables_async_transport(aiohttp_server)
793793
schema=schema, transport=transport, parse_results=True
794794
) as session:
795795

796-
query = gql("query myquery($money: Money) {toEuros(money: $money)}")
796+
query = "query myquery($money: Money) {toEuros(money: $money)}"
797797

798798
variable_values = {"money": Money(10, "DM")}
799799

800800
results = await session.execute_batch(
801801
[
802-
GraphQLRequest(document=query, variable_values=variable_values),
803-
GraphQLRequest(document=query, variable_values=variable_values),
802+
GraphQLRequest(query, variable_values=variable_values),
803+
GraphQLRequest(query, variable_values=variable_values),
804804
],
805805
serialize_variables=True,
806806
)

tests/regressions/issue_447_dsl_missing_directives/test_dsl_directives.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ def test_issue_447():
6565
client.validate(q)
6666

6767
# Creating a tree from the DocumentNode created by dsl_gql
68-
dsl_tree = node_tree(q)
68+
dsl_tree = node_tree(q.document)
6969

7070
# Creating a tree from the DocumentNode created by gql
71-
gql_tree = node_tree(gql(print_ast(q)))
71+
gql_tree = node_tree(gql(print_ast(q.document)).document)
7272

7373
print("=======")
7474
print(dsl_tree)

0 commit comments

Comments
 (0)