Skip to content

Commit 3c0bb27

Browse files
committed
Support different operation names (#21)
1 parent 6edc3b7 commit 3c0bb27

File tree

6 files changed

+123
-76
lines changed

6 files changed

+123
-76
lines changed

gql/client.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,19 @@ def __init__(
2929
):
3030
assert not (
3131
type_def and introspection
32-
), "Cant provide introspection type definition at the same time"
32+
), "Can't provide introspection type definition at the same time"
3333
if transport and fetch_schema_from_transport:
3434
assert (
3535
not schema
36-
), "Cant fetch the schema from transport if is already provided"
36+
), "Can't fetch the schema from transport if is already provided"
3737
introspection = transport.execute(parse(introspection_query)).data
3838
if introspection:
39-
assert not schema, "Cant provide introspection and schema at the same time"
39+
assert not schema, "Can't provide introspection and schema at the same time"
4040
schema = build_client_schema(introspection)
4141
elif type_def:
4242
assert (
4343
not schema
44-
), "Cant provide Type definition and schema at the same time"
44+
), "Can't provide Type definition and schema at the same time"
4545
type_def_ast = parse(type_def)
4646
schema = build_ast_schema(type_def_ast)
4747
elif schema and not transport:

gql/transport/requests.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,10 @@ def __init__(
7676
for prefix in "http://", "https://":
7777
self.session.mount(prefix, adapter)
7878

79-
def execute(self, document, variable_values=None, timeout=None):
80-
# type: (Document, Dict, int) -> ExecutionResult
79+
def execute(
80+
self, document, variable_values=None, operation_name=None, timeout=None
81+
):
82+
# type: (Document, Dict, str, int) -> ExecutionResult
8183
"""Execute the provided document AST against the configured remote server.
8284
This uses the requests library to perform a HTTP POST request to the remote server.
8385
@@ -88,7 +90,11 @@ def execute(self, document, variable_values=None, timeout=None):
8890
occurred, and is a non-empty array if an error occurred.
8991
"""
9092
query_str = print_ast(document)
91-
payload = {"query": query_str, "variables": variable_values or {}}
93+
payload = {"query": query_str} # type: Dict
94+
if variable_values:
95+
payload["variables"] = variable_values
96+
if operation_name:
97+
payload["operationName"] = operation_name
9298

9399
data_key = "json" if self.use_json else "data"
94100
post_args = {

tests/fixtures/vcr_cassettes/execute.yaml

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
11
interactions:
22
- request:
3-
body: query=%7B%0A++myFavoriteFilm%3A+film%28id%3A+%22RmlsbToz%22%29+%7B%0A++++id%0A++++title%0A++++episodeId%0A++++characters%28first%3A+5%29+%7B%0A++++++edges+%7B%0A++++++++node+%7B%0A++++++++++name%0A++++++++%7D%0A++++++%7D%0A++++%7D%0A++%7D%0A%7D%0A
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"}'
45
headers:
56
Accept:
67
- '*/*'
7-
Accept-Encoding:
8-
- gzip, deflate
9-
Connection:
10-
- keep-alive
11-
Content-Length:
12-
- '247'
138
Content-Type:
14-
- application/x-www-form-urlencoded
15-
Cookie:
16-
- csrftoken=hRIez34v4hg2Wbl8XhrbshvDIB3HmLR2L9WNTJ3SdrIQHxAKtoukxiuwQlwRJewz
9+
- application/json
1710
User-Agent:
18-
- python-requests/2.22.0
19-
x-csrftoken:
20-
- hRIez34v4hg2Wbl8XhrbshvDIB3HmLR2L9WNTJ3SdrIQHxAKtoukxiuwQlwRJewz
11+
- python-requests/2.23.0
2112
method: POST
2213
uri: http://127.0.0.1:8000/graphql
2314
response:
@@ -30,17 +21,6 @@ interactions:
3021
- '264'
3122
Content-Type:
3223
- application/json
33-
Date:
34-
- Tue, 03 Dec 2019 08:23:58 GMT
35-
Server:
36-
- WSGIServer/0.1 Python/2.7.16
37-
Set-Cookie:
38-
- csrftoken=hRIez34v4hg2Wbl8XhrbshvDIB3HmLR2L9WNTJ3SdrIQHxAKtoukxiuwQlwRJewz;
39-
expires=Tue, 01-Dec-2020 08:23:58 GMT; Max-Age=31449600; Path=/
40-
Vary:
41-
- Cookie
42-
X-Frame-Options:
43-
- SAMEORIGIN
4424
status:
4525
code: 200
4626
message: OK
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
interactions:
2+
- request:
3+
body: '{"query": "query Planet1 {\n planet(id: \"UGxhbmV0OjEw\") {\n id\n name\n }\n}\n\nquery
4+
Planet2 {\n planet(id: \"UGxhbmV0OjEx\") {\n id\n name\n }\n}\n", "operationName":
5+
"Planet2"}'
6+
headers:
7+
Accept:
8+
- '*/*'
9+
Content-Type:
10+
- application/json
11+
User-Agent:
12+
- python-requests/2.23.0
13+
method: POST
14+
uri: http://127.0.0.1:8000/graphql
15+
response:
16+
body:
17+
string: '{"data":{"planet":{"id":"UGxhbmV0OjEx","name":"Geonosis"}}}'
18+
headers:
19+
Content-Length:
20+
- '59'
21+
Content-Type:
22+
- application/json
23+
status:
24+
code: 200
25+
message: OK
26+
version: 1

tests/test_client.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,19 @@ def test_retries(execute_mock):
4040

4141
client = Client(
4242
retries=expected_retries,
43-
transport=RequestsHTTPTransport(url="http://swapi.graphene-python.org/graphql"),
43+
transport=RequestsHTTPTransport(url="http://127.0.0.1:8000/graphql"),
4444
)
4545

4646
query = gql(
4747
"""
48-
{
49-
myFavoriteFilm: film(id:"RmlsbToz") {
50-
id
51-
title
52-
episodeId
53-
}
54-
}
55-
"""
48+
{
49+
myFavoriteFilm: film(id:"RmlsbToz") {
50+
id
51+
title
52+
episodeId
53+
}
54+
}
55+
"""
5656
)
5757

5858
with pytest.raises(Exception):
@@ -73,20 +73,20 @@ def test_retries_on_transport(execute_mock):
7373
"Should be HTTPConnection", "Fake connection error"
7474
)
7575
transport = RequestsHTTPTransport(
76-
url="http://localhost:9999", retries=expected_retries,
76+
url="http://127.0.0.1:8000/graphql", retries=expected_retries,
7777
)
7878
client = Client(transport=transport)
7979

8080
query = gql(
8181
"""
82-
{
83-
myFavoriteFilm: film(id:"RmlsbToz") {
84-
id
85-
title
86-
episodeId
87-
}
88-
}
89-
"""
82+
{
83+
myFavoriteFilm: film(id:"RmlsbToz") {
84+
id
85+
title
86+
episodeId
87+
}
88+
}
89+
"""
9090
)
9191
with client: # We're using the client as context manager
9292
with pytest.raises(Exception):
@@ -116,14 +116,14 @@ def test_execute_result_error():
116116

117117
failing_query = gql(
118118
"""
119-
query getContinents {
120-
continents {
121-
code
122-
name
123-
id
124-
}
125-
}
126-
"""
119+
query getContinents {
120+
continents {
121+
code
122+
name
123+
id
124+
}
125+
}
126+
"""
127127
)
128128

129129
with pytest.raises(Exception) as exc_info:
@@ -206,7 +206,7 @@ def test_gql():
206206
username
207207
}
208208
}
209-
"""
209+
"""
210210
)
211211
result = client.execute(query)
212212
client.close()

tests/test_transport.py

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,34 @@
1+
import os
2+
13
import pytest
24
import requests
35
import vcr
46

57
from gql import Client, gql
68
from gql.transport.requests import RequestsHTTPTransport
79

8-
# https://github.com/graphql-python/swapi-graphene
10+
# We serve https://github.com/graphql-python/swapi-graphene locally:
911
URL = "http://127.0.0.1:8000/graphql"
1012

1113

14+
def use_cassette(name):
15+
16+
return vcr.use_cassette(
17+
os.path.join(
18+
os.path.dirname(__file__), "fixtures", "vcr_cassettes", name + ".yaml"
19+
),
20+
record_mod="new_episodes",
21+
)
22+
23+
1224
@pytest.fixture
1325
def client():
14-
with vcr.use_cassette("tests/fixtures/vcr_cassettes/client.yaml"):
15-
request = requests.get(
26+
with use_cassette("client"):
27+
response = requests.get(
1628
URL, headers={"Host": "swapi.graphene-python.org", "Accept": "text/html"}
1729
)
18-
request.raise_for_status()
19-
csrf = request.cookies["csrftoken"]
30+
response.raise_for_status()
31+
csrf = response.cookies["csrftoken"]
2032

2133
return Client(
2234
transport=RequestsHTTPTransport(
@@ -29,21 +41,21 @@ def client():
2941
def test_hero_name_query(client):
3042
query = gql(
3143
"""
32-
{
33-
myFavoriteFilm: film(id:"RmlsbToz") {
34-
id
35-
title
36-
episodeId
37-
characters(first:5) {
38-
edges {
39-
node {
40-
name
44+
{
45+
myFavoriteFilm: film(id:"RmlsbToz") {
46+
id
47+
title
48+
episodeId
49+
characters(first:5) {
50+
edges {
51+
node {
52+
name
53+
}
54+
}
4155
}
4256
}
4357
}
44-
}
45-
}
46-
"""
58+
"""
4759
)
4860
expected = {
4961
"myFavoriteFilm": {
@@ -61,6 +73,29 @@ def test_hero_name_query(client):
6173
},
6274
}
6375
}
64-
with vcr.use_cassette("tests/fixtures/vcr_cassettes/execute.yaml"):
76+
with use_cassette("execute"):
6577
result = client.execute(query)
6678
assert result == expected
79+
80+
81+
def test_planet_names_query(client):
82+
query = gql(
83+
"""
84+
query Planet1 {
85+
planet(id: "UGxhbmV0OjEw") {
86+
id
87+
name
88+
}
89+
}
90+
query Planet2 {
91+
planet(id: "UGxhbmV0OjEx") {
92+
id
93+
name
94+
}
95+
}
96+
"""
97+
)
98+
expected = {"planet": {"id": "UGxhbmV0OjEx", "name": "Geonosis"}}
99+
with use_cassette("execute2"):
100+
result = client.execute(query, operation_name="Planet2")
101+
assert result == expected

0 commit comments

Comments
 (0)