Skip to content

Commit 36b2170

Browse files
committed
Testing promise failure
1 parent 01f0539 commit 36b2170

File tree

5 files changed

+115
-12
lines changed

5 files changed

+115
-12
lines changed

graphql/core/defer.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def raise_exception(self):
113113
raise self.type(self.value).with_traceback(self.traceback)
114114

115115
else:
116-
exec ("""def raise_exception(self):
116+
exec("""def raise_exception(self):
117117
raise self.type, self.value, self.traceback""")
118118

119119
def catch(self, *errors):
@@ -418,13 +418,6 @@ def _next(self):
418418
self.result.add_callbacks(self._continue, self._continue)
419419
break
420420

421-
if isinstance(self.result, DeferredException):
422-
# Print the exception to stderr and stop if there aren't any
423-
# further errbacks to process
424-
sys.excepthook(self.result.type, self.result.value,
425-
self.result.traceback)
426-
return False
427-
428421

429422
def defer(func, *args, **kwargs):
430423
"""Invoke the given function that may or not may be a Deferred.

graphql/core/execution/executor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def complete_value(self, ctx, return_type, field_asts, info, result):
200200
info,
201201
resolved
202202
),
203-
lambda error: fail(GraphQLError(str(error), field_asts, error))
203+
lambda error: fail(GraphQLError(str(error.value), field_asts, error))
204204
)
205205

206206
if isinstance(result, Exception):

tests/core_execution/test_concurrent_executor.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
from graphql.core.execution import Executor
22
from graphql.core.execution.middlewares.sync import SynchronousExecutionMiddleware
3-
from graphql.core.defer import succeed, Deferred
3+
from graphql.core.defer import succeed, Deferred, fail
44
from graphql.core.language.location import SourceLocation
55
from graphql.core.language.parser import parse
66
from graphql.core.type import (GraphQLSchema, GraphQLObjectType, GraphQLField,
77
GraphQLArgument, GraphQLList, GraphQLInt, GraphQLString)
8+
from graphql.core.type.definition import GraphQLNonNull
89

910
from .utils import raise_callback_results
1011

@@ -151,6 +152,64 @@ def notPromise(self):
151152
'when using SynchronousExecutionMiddleware'}]
152153

153154

155+
def test_synchronous_executor_doesnt_support_defers():
156+
class Data(object):
157+
def promise(self):
158+
return succeed('i shouldn\'nt work')
159+
160+
def notPromise(self):
161+
return 'i should work'
162+
163+
DataType = GraphQLObjectType('DataType', {
164+
'promise': GraphQLField(GraphQLNonNull(GraphQLString)),
165+
'notPromise': GraphQLField(GraphQLString),
166+
})
167+
doc = '''
168+
query Example {
169+
promise
170+
notPromise
171+
}
172+
'''
173+
schema = GraphQLSchema(query=DataType)
174+
executor = Executor(schema, [SynchronousExecutionMiddleware()])
175+
176+
result = executor.execute(doc, Data(), operation_name='Example')
177+
assert not isinstance(result, Deferred)
178+
assert result.data is None
179+
assert result.errors == [{'locations': [SourceLocation(line=3, column=9)],
180+
'message': 'You cannot return a Deferred from a resolver '
181+
'when using SynchronousExecutionMiddleware'}]
182+
183+
184+
def test_executor_defer_failure():
185+
class Data(object):
186+
def promise(self):
187+
return fail(Exception('Something bad happened! Sucks :('))
188+
189+
def notPromise(self):
190+
return 'i should work'
191+
192+
DataType = GraphQLObjectType('DataType', {
193+
'promise': GraphQLField(GraphQLNonNull(GraphQLString)),
194+
'notPromise': GraphQLField(GraphQLString),
195+
})
196+
doc = '''
197+
query Example {
198+
promise
199+
notPromise
200+
}
201+
'''
202+
schema = GraphQLSchema(query=DataType)
203+
executor = Executor(schema)
204+
205+
result = executor.execute(doc, Data(), operation_name='Example')
206+
assert result.called
207+
result = result.result
208+
assert result.data is None
209+
assert result.errors == [{'locations': [SourceLocation(line=3, column=9)],
210+
'message': "Something bad happened! Sucks :("}]
211+
212+
154213
def test_synchronous_executor_will_synchronously_resolve():
155214
class Data(object):
156215
def promise(self):

tests/core_execution/test_deferred.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,32 @@ def test_callback_var_args():
234234
d.add_callback(lambda *args, **kwargs: holder.append((args, kwargs)), 2, 3, a=4, b=5)
235235
d.callback(1)
236236

237-
assert holder[0] == ((1, 2, 3), {'a': 4, 'b': 5})
237+
assert holder[0] == ((1, 2, 3), {'a': 4, 'b': 5})
238+
239+
240+
def test_deferred_callback_returns_another_deferred():
241+
d = Deferred()
242+
d2 = Deferred()
243+
244+
d.add_callback(lambda r: succeed(r + 5).add_callback(lambda v: v + 5))
245+
d.add_callback(lambda r: d2)
246+
d.callback(5)
247+
248+
assert d.result is d2
249+
assert d.paused
250+
assert d.called
251+
252+
d2.callback(7)
253+
assert d.result == 7
254+
assert d2.result == 7
255+
256+
257+
def test_deferred_exception_catch():
258+
def dummy_errback(deferred_exception):
259+
deferred_exception.catch(OSError)
260+
return "caught"
261+
262+
deferred = Deferred()
263+
deferred.add_errback(dummy_errback)
264+
deferred.errback(OSError())
265+
assert deferred.result == 'caught'

tests_py35/core_execution/test_asyncio_executor.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import functools
55
from graphql.core.execution import Executor
66
from graphql.core.execution.middlewares.asyncio import AsyncioExecutionMiddleware
7+
from graphql.core.language.location import SourceLocation
78
from graphql.core.type import (
89
GraphQLSchema,
910
GraphQLObjectType,
@@ -40,4 +41,26 @@ async def resolver_2(context, *_):
4041
executor = Executor(GraphQLSchema(Type), [AsyncioExecutionMiddleware()])
4142
result = await executor.execute(doc)
4243
assert not result.errors
43-
assert result.data == {'a': 'hey', 'b': 'hey2'}
44+
assert result.data == {'a': 'hey', 'b': 'hey2'}
45+
46+
@run_until_complete
47+
async def test_asyncio_py35_executor_with_error():
48+
doc = 'query Example { a, b }'
49+
50+
async def resolver(context, *_):
51+
await asyncio.sleep(0.001)
52+
return 'hey'
53+
54+
async def resolver_2(context, *_):
55+
await asyncio.sleep(0.003)
56+
raise Exception('resolver_2 failed!')
57+
58+
Type = GraphQLObjectType('Type', {
59+
'a': GraphQLField(GraphQLString, resolver=resolver),
60+
'b': GraphQLField(GraphQLString, resolver=resolver_2)
61+
})
62+
63+
executor = Executor(GraphQLSchema(Type), [AsyncioExecutionMiddleware()])
64+
result = await executor.execute(doc)
65+
assert result.errors == [{'locations': [SourceLocation(1, 20)], 'message': 'resolver_2 failed!'}]
66+
assert result.data == {'a': 'hey', 'b': None}

0 commit comments

Comments
 (0)