Skip to content

Commit 0eb4325

Browse files
committed
Support different operation names (#21)
1 parent 86b7ffe commit 0eb4325

File tree

7 files changed

+473
-100
lines changed

7 files changed

+473
-100
lines changed

gql/client.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,20 @@ def __init__(
3131
):
3232
assert not (
3333
type_def and introspection
34-
), "Cant provide introspection type definition at the same time"
34+
), "Cannot provide introspection type definition at the same time."
3535
if transport and fetch_schema_from_transport:
3636
assert (
3737
not schema
38-
), "Cant fetch the schema from transport if is already provided"
38+
), "Cannot fetch the schema from transport if is already provided."
3939
if introspection:
40-
assert not schema, "Cant provide introspection and schema at the same time"
40+
assert (
41+
not schema
42+
), "Cannot provide introspection and schema at the same time."
4143
schema = build_client_schema(introspection)
4244
elif type_def:
4345
assert (
4446
not schema
45-
), "Cant provide Type definition and schema at the same time"
47+
), "Cannot provide type definition and schema at the same time."
4648
type_def_ast = parse(type_def)
4749
schema = build_ast_schema(type_def_ast)
4850
elif schema and not transport:
@@ -71,7 +73,7 @@ def __init__(
7173
def validate(self, document):
7274
if not self.schema:
7375
raise Exception(
74-
"Cannot validate locally the document, you need to pass a schema."
76+
"Cannot validate the document locally, you need to pass a schema."
7577
)
7678
validation_errors = validate(self.schema, document)
7779
if validation_errors:

gql/transport/requests.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ def execute( # type: ignore
9696
self,
9797
document: DocumentNode,
9898
variable_values: Optional[Dict[str, Any]] = None,
99+
operation_name: Optional[str] = None,
99100
timeout: Optional[int] = None,
100101
) -> ExecutionResult:
101102
"""Execute GraphQL query.
@@ -105,6 +106,8 @@ def execute( # type: ignore
105106
106107
:param document: GraphQL query as AST Node object.
107108
:param variable_values: Dictionary of input parameters (Default: None).
109+
:param operation_name: Name of the operation that shall be executed.
110+
Only required in multi-operation documents (Default: None).
108111
:param timeout: Specifies a default timeout for requests (Default: None).
109112
:return: The result of execution.
110113
`data` is the result of executing the query, `errors` is null
@@ -115,7 +118,11 @@ def execute( # type: ignore
115118
raise TransportClosed("Transport is not connected")
116119

117120
query_str = print_ast(document)
118-
payload = {"query": query_str, "variables": variable_values or {}}
121+
payload: Dict[str, Any] = {"query": query_str}
122+
if variable_values:
123+
payload["variables"] = variable_values
124+
if operation_name:
125+
payload["operationName"] = operation_name
119126

120127
data_key = "json" if self.use_json else "data"
121128
post_args = {

tests/fixtures/vcr_cassettes/client.yaml

+223
Large diffs are not rendered by default.

tests/fixtures/vcr_cassettes/execute.yaml

-47
This file was deleted.
+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
interactions:
2+
- request:
3+
body: '{"query": "{\n myFavoriteFilm: film(id: \"RmlsbToz\") {\n id\n title\n episodeId\n characters(first:
4+
5) {\n edges {\n node {\n name\n }\n }\n }\n }\n}\n"}'
5+
headers:
6+
Accept:
7+
- '*/*'
8+
Accept-Encoding:
9+
- gzip, deflate
10+
Connection:
11+
- keep-alive
12+
Content-Length:
13+
- '204'
14+
Content-Type:
15+
- application/json
16+
Cookie:
17+
- csrftoken=hRIez34v4hg2Wbl8XhrbshvDIB3HmLR2L9WNTJ3SdrIQHxAKtoukxiuwQlwRJewz
18+
User-Agent:
19+
- python-requests/2.23.0
20+
x-csrftoken:
21+
- hRIez34v4hg2Wbl8XhrbshvDIB3HmLR2L9WNTJ3SdrIQHxAKtoukxiuwQlwRJewz
22+
method: POST
23+
uri: http://127.0.0.1:8000/graphql
24+
response:
25+
body:
26+
string: '{"data":{"myFavoriteFilm":{"id":"RmlsbToz","title":"Return of the Jedi","episodeId":6,"characters":{"edges":[{"node":{"name":"Luke
27+
Skywalker"}},{"node":{"name":"C-3PO"}},{"node":{"name":"R2-D2"}},{"node":{"name":"Darth
28+
Vader"}},{"node":{"name":"Leia Organa"}}]}}}}'
29+
headers:
30+
Content-Length:
31+
- '264'
32+
Content-Type:
33+
- application/json
34+
Date:
35+
- Sat, 16 May 2020 15:28:52 GMT
36+
Server:
37+
- WSGIServer/0.2 CPython/3.8.3
38+
Set-Cookie:
39+
- csrftoken=hRIez34v4hg2Wbl8XhrbshvDIB3HmLR2L9WNTJ3SdrIQHxAKtoukxiuwQlwRJewz;
40+
expires=Sat, 15 May 2021 15:28:52 GMT; Max-Age=31449600; Path=/; SameSite=Lax
41+
Vary:
42+
- Cookie
43+
X-Content-Type-Options:
44+
- nosniff
45+
X-Frame-Options:
46+
- DENY
47+
status:
48+
code: 200
49+
message: OK
50+
- request:
51+
body: '{"query": "query Planet($id: ID!) {\n planet(id: $id) {\n id\n name\n }\n}\n",
52+
"variables": {"id": "UGxhbmV0OjEw"}}'
53+
headers:
54+
Accept:
55+
- '*/*'
56+
Accept-Encoding:
57+
- gzip, deflate
58+
Connection:
59+
- keep-alive
60+
Content-Length:
61+
- '123'
62+
Content-Type:
63+
- application/json
64+
Cookie:
65+
- csrftoken=hRIez34v4hg2Wbl8XhrbshvDIB3HmLR2L9WNTJ3SdrIQHxAKtoukxiuwQlwRJewz
66+
User-Agent:
67+
- python-requests/2.23.0
68+
x-csrftoken:
69+
- hRIez34v4hg2Wbl8XhrbshvDIB3HmLR2L9WNTJ3SdrIQHxAKtoukxiuwQlwRJewz
70+
method: POST
71+
uri: http://127.0.0.1:8000/graphql
72+
response:
73+
body:
74+
string: '{"data":{"planet":{"id":"UGxhbmV0OjEw","name":"Kamino"}}}'
75+
headers:
76+
Content-Length:
77+
- '57'
78+
Content-Type:
79+
- application/json
80+
Date:
81+
- Sat, 16 May 2020 15:28:52 GMT
82+
Server:
83+
- WSGIServer/0.2 CPython/3.8.3
84+
Set-Cookie:
85+
- csrftoken=hRIez34v4hg2Wbl8XhrbshvDIB3HmLR2L9WNTJ3SdrIQHxAKtoukxiuwQlwRJewz;
86+
expires=Sat, 15 May 2021 15:28:52 GMT; Max-Age=31449600; Path=/; SameSite=Lax
87+
Vary:
88+
- Cookie
89+
X-Content-Type-Options:
90+
- nosniff
91+
X-Frame-Options:
92+
- DENY
93+
status:
94+
code: 200
95+
message: OK
96+
- request:
97+
body: '{"query": "query Planet1 {\n planet(id: \"UGxhbmV0OjEw\") {\n id\n name\n }\n}\n\nquery
98+
Planet2 {\n planet(id: \"UGxhbmV0OjEx\") {\n id\n name\n }\n}\n", "operationName":
99+
"Planet2"}'
100+
headers:
101+
Accept:
102+
- '*/*'
103+
Accept-Encoding:
104+
- gzip, deflate
105+
Connection:
106+
- keep-alive
107+
Content-Length:
108+
- '197'
109+
Content-Type:
110+
- application/json
111+
Cookie:
112+
- csrftoken=hRIez34v4hg2Wbl8XhrbshvDIB3HmLR2L9WNTJ3SdrIQHxAKtoukxiuwQlwRJewz
113+
User-Agent:
114+
- python-requests/2.23.0
115+
x-csrftoken:
116+
- hRIez34v4hg2Wbl8XhrbshvDIB3HmLR2L9WNTJ3SdrIQHxAKtoukxiuwQlwRJewz
117+
method: POST
118+
uri: http://127.0.0.1:8000/graphql
119+
response:
120+
body:
121+
string: '{"data":{"planet":{"id":"UGxhbmV0OjEx","name":"Geonosis"}}}'
122+
headers:
123+
Content-Length:
124+
- '59'
125+
Content-Type:
126+
- application/json
127+
Date:
128+
- Sat, 16 May 2020 15:28:52 GMT
129+
Server:
130+
- WSGIServer/0.2 CPython/3.8.3
131+
Set-Cookie:
132+
- csrftoken=hRIez34v4hg2Wbl8XhrbshvDIB3HmLR2L9WNTJ3SdrIQHxAKtoukxiuwQlwRJewz;
133+
expires=Sat, 15 May 2021 15:28:52 GMT; Max-Age=31449600; Path=/; SameSite=Lax
134+
Vary:
135+
- Cookie
136+
X-Content-Type-Options:
137+
- nosniff
138+
X-Frame-Options:
139+
- DENY
140+
status:
141+
code: 200
142+
message: OK
143+
version: 1

tests/test_client.py

+25-25
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
def http_transport_query():
1414
return gql(
1515
"""
16-
query getContinents {
17-
continents {
18-
code
19-
name
20-
}
21-
}
22-
"""
16+
query getContinents {
17+
continents {
18+
code
19+
name
20+
}
21+
}
22+
"""
2323
)
2424

2525

@@ -45,20 +45,20 @@ def test_retries_on_transport(execute_mock):
4545
"Should be HTTPConnection", "Fake connection error"
4646
)
4747
transport = RequestsHTTPTransport(
48-
url="http://127.0.0.1:9999", retries=expected_retries,
48+
url="http://127.0.0.1:8000/graphql", retries=expected_retries,
4949
)
5050
client = Client(transport=transport)
5151

5252
query = gql(
5353
"""
54-
{
55-
myFavoriteFilm: film(id:"RmlsbToz") {
56-
id
57-
title
58-
episodeId
59-
}
60-
}
61-
"""
54+
{
55+
myFavoriteFilm: film(id:"RmlsbToz") {
56+
id
57+
title
58+
episodeId
59+
}
60+
}
61+
"""
6262
)
6363
with client as session: # We're using the client as context manager
6464
with pytest.raises(Exception):
@@ -86,14 +86,14 @@ def test_execute_result_error():
8686

8787
failing_query = gql(
8888
"""
89-
query getContinents {
90-
continents {
91-
code
92-
name
93-
id
94-
}
95-
}
96-
"""
89+
query getContinents {
90+
continents {
91+
code
92+
name
93+
id
94+
}
95+
}
96+
"""
9797
)
9898

9999
with pytest.raises(Exception) as exc_info:
@@ -167,7 +167,7 @@ def test_gql():
167167
username
168168
}
169169
}
170-
"""
170+
"""
171171
)
172172

173173
client = Client(schema=schema)

0 commit comments

Comments
 (0)