Skip to content

Commit c698ab5

Browse files
committed
refactor: introduce complete_list_item_value
Replicates graphql/graphql-js@40ff40a
1 parent 3d3393f commit c698ab5

File tree

2 files changed

+94
-100
lines changed

2 files changed

+94
-100
lines changed

src/graphql/execution/execute.py

+93-100
Original file line numberDiff line numberDiff line change
@@ -1177,11 +1177,10 @@ async def complete_async_iterator_value(
11771177
"""
11781178
errors = async_payload_record.errors if async_payload_record else self.errors
11791179
stream = self.get_stream_values(field_nodes, path)
1180-
is_awaitable = self.is_awaitable
1180+
complete_list_item_value = self.complete_list_item_value
11811181
awaitable_indices: List[int] = []
11821182
append_awaitable = awaitable_indices.append
11831183
completed_results: List[Any] = []
1184-
append_result = completed_results.append
11851184
index = 0
11861185
while True:
11871186
if (
@@ -1213,46 +1212,23 @@ async def complete_async_iterator_value(
12131212
value = await anext(iterator)
12141213
except StopAsyncIteration:
12151214
break
1216-
try:
1217-
completed_item = self.complete_value(
1218-
item_type,
1219-
field_nodes,
1220-
info,
1221-
item_path,
1222-
value,
1223-
async_payload_record,
1224-
)
1225-
if is_awaitable(completed_item):
1226-
# noinspection PyShadowingNames
1227-
async def catch_error(
1228-
completed_item: Awaitable[Any], item_path: Path
1229-
) -> Any:
1230-
try:
1231-
return await completed_item
1232-
except Exception as raw_error:
1233-
error = located_error(
1234-
raw_error, field_nodes, item_path.as_list()
1235-
)
1236-
self.filter_subsequent_payloads(
1237-
item_path, async_payload_record
1238-
)
1239-
handle_field_error(error, item_type, errors)
1240-
return None
1241-
1242-
append_result(catch_error(completed_item, item_path))
1243-
append_awaitable(index)
1244-
else:
1245-
append_result(completed_item)
1246-
except Exception as raw_error:
1247-
append_result(None)
1248-
error = located_error(raw_error, field_nodes, item_path.as_list())
1249-
self.filter_subsequent_payloads(item_path, async_payload_record)
1250-
handle_field_error(error, item_type, errors)
12511215
except Exception as raw_error:
1252-
append_result(None)
12531216
error = located_error(raw_error, field_nodes, item_path.as_list())
12541217
handle_field_error(error, item_type, errors)
1218+
completed_results.append(None)
12551219
break
1220+
if complete_list_item_value(
1221+
value,
1222+
completed_results,
1223+
errors,
1224+
item_type,
1225+
field_nodes,
1226+
info,
1227+
item_path,
1228+
async_payload_record,
1229+
):
1230+
append_awaitable(index)
1231+
12561232
index += 1
12571233

12581234
if not awaitable_indices:
@@ -1307,12 +1283,11 @@ def complete_list_value(
13071283
# This is specified as a simple map, however we're optimizing the path where
13081284
# the list contains no coroutine objects by avoiding creating another coroutine
13091285
# object.
1310-
is_awaitable = self.is_awaitable
1286+
complete_list_item_value = self.complete_list_item_value
13111287
awaitable_indices: List[int] = []
13121288
append_awaitable = awaitable_indices.append
13131289
previous_async_payload_record = async_payload_record
13141290
completed_results: List[Any] = []
1315-
append_result = completed_results.append
13161291
for index, item in enumerate(result):
13171292
# No need to modify the info object containing the path, since from here on
13181293
# it is not ever accessed by resolver functions.
@@ -1335,67 +1310,17 @@ def complete_list_value(
13351310
)
13361311
continue
13371312

1338-
completed_item: AwaitableOrValue[Any]
1339-
1340-
if is_awaitable(item):
1341-
# noinspection PyShadowingNames
1342-
async def await_completed(item: Any, item_path: Path) -> Any:
1343-
try:
1344-
completed = self.complete_value(
1345-
item_type,
1346-
field_nodes,
1347-
info,
1348-
item_path,
1349-
await item,
1350-
async_payload_record,
1351-
)
1352-
if is_awaitable(completed):
1353-
return await completed
1354-
except Exception as raw_error:
1355-
error = located_error(
1356-
raw_error, field_nodes, item_path.as_list()
1357-
)
1358-
handle_field_error(error, item_type, errors)
1359-
self.filter_subsequent_payloads(item_path, async_payload_record)
1360-
return None
1361-
return completed
1362-
1363-
completed_item = await_completed(item, item_path)
1364-
else:
1365-
try:
1366-
completed_item = self.complete_value(
1367-
item_type,
1368-
field_nodes,
1369-
info,
1370-
item_path,
1371-
item,
1372-
async_payload_record,
1373-
)
1374-
if is_awaitable(completed_item):
1375-
# noinspection PyShadowingNames
1376-
async def await_completed(item: Any, item_path: Path) -> Any:
1377-
try:
1378-
return await item
1379-
except Exception as raw_error:
1380-
error = located_error(
1381-
raw_error, field_nodes, item_path.as_list()
1382-
)
1383-
handle_field_error(error, item_type, errors)
1384-
self.filter_subsequent_payloads(
1385-
item_path, async_payload_record
1386-
)
1387-
return None
1388-
1389-
completed_item = await_completed(completed_item, item_path)
1390-
except Exception as raw_error:
1391-
error = located_error(raw_error, field_nodes, item_path.as_list())
1392-
handle_field_error(error, item_type, errors)
1393-
self.filter_subsequent_payloads(item_path, async_payload_record)
1394-
completed_item = None
1395-
1396-
if is_awaitable(completed_item):
1313+
if complete_list_item_value(
1314+
item,
1315+
completed_results,
1316+
errors,
1317+
item_type,
1318+
field_nodes,
1319+
info,
1320+
item_path,
1321+
async_payload_record,
1322+
):
13971323
append_awaitable(index)
1398-
append_result(completed_item)
13991324

14001325
if not awaitable_indices:
14011326
return completed_results
@@ -1418,6 +1343,74 @@ async def get_completed_results() -> List[Any]:
14181343

14191344
return get_completed_results()
14201345

1346+
def complete_list_item_value(
1347+
self,
1348+
item: Any,
1349+
complete_results: List[Any],
1350+
errors: List[GraphQLError],
1351+
item_type: GraphQLOutputType,
1352+
field_nodes: List[FieldNode],
1353+
info: GraphQLResolveInfo,
1354+
item_path: Path,
1355+
async_payload_record: Optional[AsyncPayloadRecord],
1356+
) -> bool:
1357+
"""Complete a list item value by adding it to the completed results.
1358+
1359+
Returns True if the value is awaitable.
1360+
"""
1361+
is_awaitable = self.is_awaitable
1362+
try:
1363+
if is_awaitable(item):
1364+
completed_item: Any
1365+
1366+
async def await_completed() -> Any:
1367+
completed = self.complete_value(
1368+
item_type,
1369+
field_nodes,
1370+
info,
1371+
item_path,
1372+
await item,
1373+
async_payload_record,
1374+
)
1375+
return await completed if is_awaitable(completed) else completed
1376+
1377+
completed_item = await_completed()
1378+
else:
1379+
completed_item = self.complete_value(
1380+
item_type,
1381+
field_nodes,
1382+
info,
1383+
item_path,
1384+
item,
1385+
async_payload_record,
1386+
)
1387+
1388+
if is_awaitable(completed_item):
1389+
# noinspection PyShadowingNames
1390+
async def catch_error() -> Any:
1391+
try:
1392+
return await completed_item
1393+
except Exception as raw_error:
1394+
error = located_error(
1395+
raw_error, field_nodes, item_path.as_list()
1396+
)
1397+
handle_field_error(error, item_type, errors)
1398+
self.filter_subsequent_payloads(item_path, async_payload_record)
1399+
return None
1400+
1401+
complete_results.append(catch_error())
1402+
return True
1403+
1404+
complete_results.append(completed_item)
1405+
1406+
except Exception as raw_error:
1407+
error = located_error(raw_error, field_nodes, item_path.as_list())
1408+
handle_field_error(error, item_type, errors)
1409+
self.filter_subsequent_payloads(item_path, async_payload_record)
1410+
complete_results.append(None)
1411+
1412+
return False
1413+
14211414
@staticmethod
14221415
def complete_leaf_value(return_type: GraphQLLeafType, result: Any) -> Any:
14231416
"""Complete a leaf value.

tests/execution/test_stream.py

+1
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,7 @@ async def friend_list(_info):
12301230
}
12311231

12321232
@pytest.mark.asyncio()
1233+
@pytest.mark.filterwarnings("ignore:.* was never awaited:RuntimeWarning")
12331234
async def does_not_filter_payloads_when_null_error_is_in_a_different_path():
12341235
document = parse(
12351236
"""

0 commit comments

Comments
 (0)