Skip to content

Commit 1fce663

Browse files
author
m.kindritskiy
committed
rewrite GrapQLError
1 parent 8d19c91 commit 1fce663

21 files changed

+516
-395
lines changed

.flake8

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[flake8]
22
max-line-length = 80
33
exclude = *_pb2.py,.tox,.git,env,docs,.venv,__pypackages__,tests
4-
extend-ignore = E203
4+
extend-ignore = E203,E231
55
ignore =
66
F811,
77
W503,

docs/changelog/changes_08.rst

+9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ Changes in 0.8
2020
- Change `GraphQLResponse` type - it now has both `data` and `errors` fields
2121
- Rename `on_dispatch` hook to `on_operation`
2222
- Remove old `on_operation` hook
23+
- Remove `execute` method from `BaseGraphQLEndpoint` class
24+
- Add `process_result` method to `BaseGraphQLEndpoint` class
25+
- Move `GraphQLError` to `hiku.error` module
26+
- Drop `GraphQLError.errors` field. Earlier we used to store multiple errors in single `GraphQLError` but now its one message - one `GraphQLError`.
27+
- Add `GraphQLError.message` field
2328

2429
Backward-incompatible changes
2530
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -29,3 +34,7 @@ Backward-incompatible changes
2934
- Drop `hiku.federation.endpoint` - use `hiku.endpoint` instead
3035
- Drop `hiku.federation.denormalize`
3136
- Drop `hiku.federation.engine` - use `hiku.engine` instead
37+
- Remove `execute` method from `BaseGraphQLEndpoint` class
38+
- Move `GraphQLError` to `hiku.error` module
39+
- Drop `GraphQLError.errors` field
40+
- Add `GraphQLError.message` field

examples/federation-compatibility/server.py

+12-9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from flask import Flask, request, jsonify
77

88
from hiku.directives import Deprecated, Location
9+
from hiku.endpoint.graphql import GraphQLEndpoint
10+
from hiku.federation.schema import Schema
911
from hiku.federation.directive import (
1012
Extends,
1113
FederationSchemaDirective,
@@ -29,7 +31,6 @@
2931
Node,
3032
Link,
3133
)
32-
from hiku.schema import Schema
3334
from hiku.types import (
3435
Float,
3536
ID,
@@ -408,7 +409,7 @@ class Custom(FederationSchemaDirective):
408409
),
409410
],
410411
directives=[Key("email"), Extends()],
411-
resolve_reference=resolve_reference_by('email')
412+
resolve_reference=resolve_reference_by("email"),
412413
),
413414
FederatedNode(
414415
"Product",
@@ -454,7 +455,7 @@ class Custom(FederationSchemaDirective):
454455
Key("sku package"),
455456
Key("sku variation { id }"),
456457
],
457-
resolve_reference=resolve_reference_direct
458+
resolve_reference=resolve_reference_direct,
458459
),
459460
Node(
460461
"ProductDimension",
@@ -489,7 +490,7 @@ class Custom(FederationSchemaDirective):
489490
),
490491
],
491492
directives=[Key("study { caseNumber }")],
492-
resolve_reference=resolve_reference_direct
493+
resolve_reference=resolve_reference_direct,
493494
),
494495
FederatedNode(
495496
"DeprecatedProduct",
@@ -573,22 +574,24 @@ class Custom(FederationSchemaDirective):
573574
QUERY_GRAPH,
574575
)
575576

577+
endpoint = GraphQLEndpoint(schema)
578+
576579

577580
@app.route("/graphql", methods={"POST"})
578581
def handle_graphql():
579582
data = request.get_json()
580-
result = schema.execute_sync(data)
583+
result = endpoint.dispatch(data)
581584
resp = jsonify(result)
582585
return resp
583586

584587

585-
@app.route('/', methods={'GET'})
588+
@app.route("/", methods={"GET"})
586589
def graphiql():
587-
path = Path(__file__).parent.parent / 'graphiql.html'
590+
path = Path(__file__).parent.parent / "graphiql.html"
588591
with open(path) as f:
589592
page = f.read()
590593
page = page.replace("localhost:5000", "localhost:4001")
591-
return page.encode('utf-8')
594+
return page.encode("utf-8")
592595

593596

594597
def main():
@@ -600,7 +603,7 @@ def main():
600603
def dump():
601604
from hiku.federation.sdl import print_sdl
602605

603-
out_file = Path(__file__).resolve().parent / 'products.graphql'
606+
out_file = Path(__file__).resolve().parent / "products.graphql"
604607
print(f"Dumping schema to {out_file}")
605608
sdl = print_sdl(QUERY_GRAPH)
606609
with open(out_file, "w") as f:

examples/graphql_aiohttp.py

+50-27
Original file line numberDiff line numberDiff line change
@@ -19,57 +19,80 @@
1919

2020

2121
async def value_func(fields):
22-
return ['Hello World!' for _ in fields]
22+
return ["Hello World!" for _ in fields]
2323

2424

2525
async def action_func(fields):
2626
results = []
2727
for field in fields:
28-
print('action performed!', field.options)
28+
print("action performed!", field.options)
2929
results.append(True)
3030
return results
3131

3232

3333
DATA_TYPES = {
34-
'Point': Record[{
35-
'x': Integer,
36-
'y': Integer,
37-
}],
38-
'Data': Record[{
39-
'point': TypeRef['Point'],
40-
}],
34+
"Point": Record[
35+
{
36+
"x": Integer,
37+
"y": Integer,
38+
}
39+
],
40+
"Data": Record[
41+
{
42+
"point": TypeRef["Point"],
43+
}
44+
],
4145
}
4246

43-
QUERY_GRAPH = Graph([
44-
Root([
45-
Field('value', String, value_func),
46-
]),
47-
], data_types=DATA_TYPES)
47+
QUERY_GRAPH = Graph(
48+
[
49+
Root(
50+
[
51+
Field("value", String, value_func),
52+
]
53+
),
54+
],
55+
data_types=DATA_TYPES,
56+
)
4857

49-
MUTATION_GRAPH = Graph(QUERY_GRAPH.nodes + [
50-
Root([
51-
Field('action', Boolean, action_func,
52-
options=[Option('data', TypeRef['Data'])]),
53-
]),
54-
], data_types=DATA_TYPES)
58+
MUTATION_GRAPH = Graph(
59+
QUERY_GRAPH.nodes
60+
+ [
61+
Root(
62+
[
63+
Field(
64+
"action",
65+
Boolean,
66+
action_func,
67+
options=[Option("data", TypeRef["Data"])],
68+
),
69+
]
70+
),
71+
],
72+
data_types=DATA_TYPES,
73+
)
5574

5675

5776
async def handle_graphql(request):
5877
data = await request.json()
59-
result = await request.app['graphql-endpoint'].dispatch(data)
78+
result = await request.app["graphql-endpoint"].dispatch(data)
6079
return web.json_response(result)
6180

6281

6382
def main():
6483
logging.basicConfig(level=logging.DEBUG)
6584
app = web.Application()
66-
app.add_routes([
67-
web.post('/graphql', handle_graphql),
68-
])
69-
app['graphql-endpoint'] = AsyncGraphQLEndpoint(
70-
Engine(AsyncIOExecutor()), QUERY_GRAPH, MUTATION_GRAPH,
85+
app.add_routes(
86+
[
87+
web.post("/graphql", handle_graphql),
88+
]
89+
)
90+
app["graphql-endpoint"] = AsyncGraphQLEndpoint(
91+
Engine(AsyncIOExecutor()),
92+
QUERY_GRAPH,
93+
MUTATION_GRAPH,
7194
)
72-
web.run_app(app, host='0.0.0.0', port=5000)
95+
web.run_app(app, host="0.0.0.0", port=5000)
7396

7497

7598
if __name__ == "__main__":

examples/graphql_federation.py

+65-45
Original file line numberDiff line numberDiff line change
@@ -31,52 +31,56 @@
3131

3232
def get_by_id(id_, collection):
3333
for item in collection:
34-
if item['id'] == id_:
34+
if item["id"] == id_:
3535
return item
3636

3737

38-
def find_all_by_id(id_, collection, key='id'):
38+
def find_all_by_id(id_, collection, key="id"):
3939
for item in collection:
4040
if item[key] == id_:
4141
yield item
4242

4343

4444
data = {
45-
'carts': [
46-
dict(id=1, status='NEW'),
47-
dict(id=2, status='ORDERED'),
45+
"carts": [
46+
dict(id=1, status="NEW"),
47+
dict(id=2, status="ORDERED"),
48+
],
49+
"cart_items": [
50+
dict(id=10, cart_id=1, name="Ipad"),
51+
dict(id=20, cart_id=2, name="Book"),
52+
dict(id=21, cart_id=2, name="Pen"),
4853
],
49-
'cart_items': [
50-
dict(id=10, cart_id=1, name='Ipad'),
51-
dict(id=20, cart_id=2, name='Book'),
52-
dict(id=21, cart_id=2, name='Pen'),
53-
]
5454
}
5555

5656

5757
@listify
5858
def cart_resolver(fields, ids):
5959
for cart_id in ids:
60-
cart = get_by_id(cart_id, data['carts'])
60+
cart = get_by_id(cart_id, data["carts"])
6161
yield [cart[f.name] for f in fields]
6262

6363

6464
@listify
6565
def cart_item_resolver(fields, ids):
6666
for item_id in ids:
67-
item = get_by_id(item_id, data['cart_items'])
67+
item = get_by_id(item_id, data["cart_items"])
6868
yield [item[f.name] for f in fields]
6969

7070

7171
@listify
7272
def link_cart_items(cart_ids):
7373
for cart_id in cart_ids:
74-
yield [item['id'] for item
75-
in find_all_by_id(cart_id, data['cart_items'], key='cart_id')]
74+
yield [
75+
item["id"]
76+
for item in find_all_by_id(
77+
cart_id, data["cart_items"], key="cart_id"
78+
)
79+
]
7680

7781

7882
def direct_link_id(opts):
79-
return opts['id']
83+
return opts["id"]
8084

8185

8286
def ids_resolver(fields, ids):
@@ -94,35 +98,51 @@ def direct_link(ids):
9498
9599
This `cart` subgraph extends `order`'s subgraph type `Order` with `cart` field
96100
"""
97-
QUERY_GRAPH = Graph([
98-
Node('Order', [
99-
Field('cartId', Integer, ids_resolver,
100-
directives=[External()]),
101-
Link('cart', TypeRef['Cart'], direct_link, requires='cartId'),
102-
], directives=[Key('cartId'), Extends()]),
103-
Node('Cart', [
104-
Field('id', Integer, cart_resolver),
105-
Field('status', String, cart_resolver),
106-
Link('items', Sequence[TypeRef['CartItem']], link_cart_items,
107-
requires='id')
108-
], directives=[Key('id')]),
109-
Node('CartItem', [
110-
Field('id', Integer, cart_item_resolver),
111-
Field('cart_id', Integer, cart_item_resolver),
112-
Field('name', String, cart_item_resolver),
113-
]),
114-
Root([
115-
Link(
116-
'cart',
117-
Optional[TypeRef['Cart']],
118-
direct_link_id,
119-
requires=None,
120-
options=[
121-
Option('id', Integer)
101+
QUERY_GRAPH = Graph(
102+
[
103+
Node(
104+
"Order",
105+
[
106+
Field("cartId", Integer, ids_resolver, directives=[External()]),
107+
Link("cart", TypeRef["Cart"], direct_link, requires="cartId"),
122108
],
109+
directives=[Key("cartId"), Extends()],
123110
),
124-
]),
125-
])
111+
Node(
112+
"Cart",
113+
[
114+
Field("id", Integer, cart_resolver),
115+
Field("status", String, cart_resolver),
116+
Link(
117+
"items",
118+
Sequence[TypeRef["CartItem"]],
119+
link_cart_items,
120+
requires="id",
121+
),
122+
],
123+
directives=[Key("id")],
124+
),
125+
Node(
126+
"CartItem",
127+
[
128+
Field("id", Integer, cart_item_resolver),
129+
Field("cart_id", Integer, cart_item_resolver),
130+
Field("name", String, cart_item_resolver),
131+
],
132+
),
133+
Root(
134+
[
135+
Link(
136+
"cart",
137+
Optional[TypeRef["Cart"]],
138+
direct_link_id,
139+
requires=None,
140+
options=[Option("id", Integer)],
141+
),
142+
]
143+
),
144+
]
145+
)
126146

127147

128148
app = Flask(__name__)
@@ -134,7 +154,7 @@ def direct_link(ids):
134154
)
135155

136156

137-
@app.route('/graphql', methods={'POST'})
157+
@app.route("/graphql", methods={"POST"})
138158
def handle_graphql():
139159
data = request.get_json()
140160
result = schema.execute_sync(data)
@@ -144,8 +164,8 @@ def handle_graphql():
144164

145165
def main():
146166
logging.basicConfig(level=logging.DEBUG)
147-
app.run(host='0.0.0.0', port=5000, debug=True)
167+
app.run(host="0.0.0.0", port=5000, debug=True)
148168

149169

150-
if __name__ == '__main__':
170+
if __name__ == "__main__":
151171
main()

0 commit comments

Comments
 (0)