|
20 | 20 | GraphQLResolveInfo,
|
21 | 21 | ResponsePath,
|
22 | 22 | )
|
| 23 | +from .util import compare_query_results_unordered |
23 | 24 |
|
24 | 25 |
|
25 | 26 | def describe_execute_handles_basic_execution_tasks():
|
@@ -417,67 +418,70 @@ async def asyncReturnErrorWithExtensions(self, _info):
|
417 | 418 | )
|
418 | 419 | )
|
419 | 420 |
|
420 |
| - assert await execute(schema, ast, Data()) == ( |
421 |
| - { |
422 |
| - "syncOk": "sync ok", |
423 |
| - "syncError": None, |
424 |
| - "syncRawError": None, |
425 |
| - "syncReturnError": None, |
426 |
| - "syncReturnErrorList": ["sync0", None, "sync2", None], |
427 |
| - "asyncOk": "async ok", |
428 |
| - "asyncError": None, |
429 |
| - "asyncRawError": None, |
430 |
| - "asyncReturnError": None, |
431 |
| - "asyncReturnErrorWithExtensions": None, |
432 |
| - }, |
433 |
| - [ |
434 |
| - { |
435 |
| - "message": "Error getting syncError", |
436 |
| - "locations": [(3, 15)], |
437 |
| - "path": ["syncError"], |
438 |
| - }, |
439 |
| - { |
440 |
| - "message": "Error getting syncRawError", |
441 |
| - "locations": [(4, 15)], |
442 |
| - "path": ["syncRawError"], |
443 |
| - }, |
444 |
| - { |
445 |
| - "message": "Error getting syncReturnError", |
446 |
| - "locations": [(5, 15)], |
447 |
| - "path": ["syncReturnError"], |
448 |
| - }, |
449 |
| - { |
450 |
| - "message": "Error getting syncReturnErrorList1", |
451 |
| - "locations": [(6, 15)], |
452 |
| - "path": ["syncReturnErrorList", 1], |
453 |
| - }, |
454 |
| - { |
455 |
| - "message": "Error getting syncReturnErrorList3", |
456 |
| - "locations": [(6, 15)], |
457 |
| - "path": ["syncReturnErrorList", 3], |
458 |
| - }, |
459 |
| - { |
460 |
| - "message": "Error getting asyncError", |
461 |
| - "locations": [(8, 15)], |
462 |
| - "path": ["asyncError"], |
463 |
| - }, |
464 |
| - { |
465 |
| - "message": "Error getting asyncRawError", |
466 |
| - "locations": [(9, 15)], |
467 |
| - "path": ["asyncRawError"], |
468 |
| - }, |
469 |
| - { |
470 |
| - "message": "Error getting asyncReturnError", |
471 |
| - "locations": [(10, 15)], |
472 |
| - "path": ["asyncReturnError"], |
473 |
| - }, |
| 421 | + compare_query_results_unordered( |
| 422 | + await execute(schema, ast, Data()), |
| 423 | + ( |
474 | 424 | {
|
475 |
| - "message": "Error getting asyncReturnErrorWithExtensions", |
476 |
| - "locations": [(11, 15)], |
477 |
| - "path": ["asyncReturnErrorWithExtensions"], |
478 |
| - "extensions": {"foo": "bar"}, |
| 425 | + "syncOk": "sync ok", |
| 426 | + "syncError": None, |
| 427 | + "syncRawError": None, |
| 428 | + "syncReturnError": None, |
| 429 | + "syncReturnErrorList": ["sync0", None, "sync2", None], |
| 430 | + "asyncOk": "async ok", |
| 431 | + "asyncError": None, |
| 432 | + "asyncRawError": None, |
| 433 | + "asyncReturnError": None, |
| 434 | + "asyncReturnErrorWithExtensions": None, |
479 | 435 | },
|
480 |
| - ], |
| 436 | + [ |
| 437 | + { |
| 438 | + "message": "Error getting syncError", |
| 439 | + "locations": [(3, 15)], |
| 440 | + "path": ["syncError"], |
| 441 | + }, |
| 442 | + { |
| 443 | + "message": "Error getting syncRawError", |
| 444 | + "locations": [(4, 15)], |
| 445 | + "path": ["syncRawError"], |
| 446 | + }, |
| 447 | + { |
| 448 | + "message": "Error getting syncReturnError", |
| 449 | + "locations": [(5, 15)], |
| 450 | + "path": ["syncReturnError"], |
| 451 | + }, |
| 452 | + { |
| 453 | + "message": "Error getting syncReturnErrorList1", |
| 454 | + "locations": [(6, 15)], |
| 455 | + "path": ["syncReturnErrorList", 1], |
| 456 | + }, |
| 457 | + { |
| 458 | + "message": "Error getting syncReturnErrorList3", |
| 459 | + "locations": [(6, 15)], |
| 460 | + "path": ["syncReturnErrorList", 3], |
| 461 | + }, |
| 462 | + { |
| 463 | + "message": "Error getting asyncError", |
| 464 | + "locations": [(8, 15)], |
| 465 | + "path": ["asyncError"], |
| 466 | + }, |
| 467 | + { |
| 468 | + "message": "Error getting asyncRawError", |
| 469 | + "locations": [(9, 15)], |
| 470 | + "path": ["asyncRawError"], |
| 471 | + }, |
| 472 | + { |
| 473 | + "message": "Error getting asyncReturnError", |
| 474 | + "locations": [(10, 15)], |
| 475 | + "path": ["asyncReturnError"], |
| 476 | + }, |
| 477 | + { |
| 478 | + "message": "Error getting asyncReturnErrorWithExtensions", |
| 479 | + "locations": [(11, 15)], |
| 480 | + "path": ["asyncReturnErrorWithExtensions"], |
| 481 | + "extensions": {"foo": "bar"}, |
| 482 | + }, |
| 483 | + ], |
| 484 | + ), |
481 | 485 | )
|
482 | 486 |
|
483 | 487 | def full_response_path_is_included_for_non_nullable_fields():
|
@@ -866,3 +870,42 @@ def resolve_field(self, parent_type, source, field_nodes, path):
|
866 | 870 | {"foo": "barbar"},
|
867 | 871 | None,
|
868 | 872 | )
|
| 873 | + |
| 874 | + @mark.asyncio |
| 875 | + async def resolve_fields_in_parallel(): |
| 876 | + class Barrier(object): |
| 877 | + # Makes progress only if at least `count` callers are `wait()`ing. |
| 878 | + def __init__(self, count): |
| 879 | + self.ev = asyncio.Event() |
| 880 | + self.count = count |
| 881 | + |
| 882 | + async def wait(self): |
| 883 | + self.count -= 1 |
| 884 | + if self.count == 0: |
| 885 | + self.ev.set() |
| 886 | + |
| 887 | + return await self.ev.wait() |
| 888 | + |
| 889 | + barrier = Barrier(2) |
| 890 | + |
| 891 | + async def f(*args): |
| 892 | + return await barrier.wait() |
| 893 | + |
| 894 | + schema = GraphQLSchema( |
| 895 | + GraphQLObjectType( |
| 896 | + "Object", |
| 897 | + { |
| 898 | + "foo": GraphQLField(GraphQLBoolean, resolve=f), |
| 899 | + "bar": GraphQLField(GraphQLBoolean, resolve=f), |
| 900 | + }, |
| 901 | + ) |
| 902 | + ) |
| 903 | + |
| 904 | + query = "{foo, bar}" |
| 905 | + ast = parse(query) |
| 906 | + |
| 907 | + res = await asyncio.wait_for( |
| 908 | + execute(schema, ast), 1.0 # don't wait forever for the test to fail |
| 909 | + ) |
| 910 | + |
| 911 | + assert res == ({"foo": True, "bar": True}, None) |
0 commit comments