Skip to content

Commit 1a62f30

Browse files
committed
Use is_awaitable more consistently
1 parent a46cc84 commit 1a62f30

File tree

10 files changed

+30
-34
lines changed

10 files changed

+30
-34
lines changed

src/graphql/execution/execute.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from asyncio import Event, as_completed, ensure_future, gather, shield, sleep, wait_for
44
from collections.abc import Mapping
55
from contextlib import suppress
6-
from inspect import isawaitable
76
from typing import (
87
Any,
98
AsyncGenerator,
@@ -1646,7 +1645,7 @@ def map_source_to_response(
16461645
async def callback(payload: Any) -> AsyncGenerator:
16471646
result = execute_impl(self.build_per_event_execution_context(payload))
16481647
return ensure_async_iterable(
1649-
await result if isawaitable(result) else result # type: ignore
1648+
await result if self.is_awaitable(result) else result # type: ignore
16501649
)
16511650

16521651
return flatten_async_iterable(map_async_iterable(result_or_stream, callback))
@@ -2124,7 +2123,7 @@ async def await_result() -> Any:
21242123

21252124

21262125
def assume_not_awaitable(_value: Any) -> bool:
2127-
"""Replacement for isawaitable if everything is assumed to be synchronous."""
2126+
"""Replacement for is_awaitable if everything is assumed to be synchronous."""
21282127
return False
21292128

21302129

@@ -2172,10 +2171,10 @@ def execute_sync(
21722171
)
21732172

21742173
# Assert that the execution was synchronous.
2175-
if isawaitable(result) or isinstance(
2174+
if default_is_awaitable(result) or isinstance(
21762175
result, ExperimentalIncrementalExecutionResults
21772176
):
2178-
if isawaitable(result):
2177+
if default_is_awaitable(result):
21792178
ensure_future(cast(Awaitable[ExecutionResult], result)).cancel()
21802179
raise RuntimeError("GraphQL execution failed to complete synchronously.")
21812180

src/graphql/graphql.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
from asyncio import ensure_future
2-
from inspect import isawaitable
32
from typing import Any, Awaitable, Callable, Dict, Optional, Type, Union, cast
43

54
from .error import GraphQLError
65
from .execution import ExecutionContext, ExecutionResult, Middleware, execute
76
from .language import Source, parse
87
from .pyutils import AwaitableOrValue
8+
from .pyutils import is_awaitable as default_is_awaitable
99
from .type import (
1010
GraphQLFieldResolver,
1111
GraphQLSchema,
@@ -92,14 +92,14 @@ async def graphql(
9292
is_awaitable,
9393
)
9494

95-
if isawaitable(result):
95+
if default_is_awaitable(result):
9696
return await cast(Awaitable[ExecutionResult], result)
9797

9898
return cast(ExecutionResult, result)
9999

100100

101101
def assume_not_awaitable(_value: Any) -> bool:
102-
"""Replacement for isawaitable if everything is assumed to be synchronous."""
102+
"""Replacement for is_awaitable if everything is assumed to be synchronous."""
103103
return False
104104

105105

@@ -145,7 +145,7 @@ def graphql_sync(
145145
)
146146

147147
# Assert that the execution was synchronous.
148-
if isawaitable(result):
148+
if default_is_awaitable(result):
149149
ensure_future(cast(Awaitable[ExecutionResult], result)).cancel()
150150
raise RuntimeError("GraphQL execution failed to complete synchronously.")
151151

src/graphql/pyutils/is_awaitable.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515

1616

1717
def is_awaitable(value: Any) -> TypeGuard[Awaitable]:
18-
"""Return true if object can be passed to an ``await`` expression.
18+
"""Return True if object can be passed to an ``await`` expression.
1919
20-
Instead of testing if the object is an instance of abc.Awaitable, it checks
21-
the existence of an `__await__` attribute. This is much faster.
20+
Instead of testing whether the object is an instance of abc.Awaitable, we
21+
check the existence of an `__await__` attribute. This is much faster.
2222
"""
2323
return (
2424
# check for coroutine objects

src/graphql/pyutils/simple_pub_sub.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from __future__ import annotations # Python < 3.10
22

33
from asyncio import Future, Queue, create_task, get_running_loop, sleep
4-
from inspect import isawaitable
54
from typing import Any, AsyncIterator, Callable, Optional, Set
65

6+
from .is_awaitable import is_awaitable
7+
78

89
__all__ = ["SimplePubSub", "SimplePubSubIterator"]
910

@@ -25,7 +26,7 @@ def emit(self, event: Any) -> bool:
2526
"""Emit an event."""
2627
for subscriber in self.subscribers:
2728
result = subscriber(event)
28-
if isawaitable(result):
29+
if is_awaitable(result):
2930
create_task(result) # type: ignore
3031
return bool(self.subscribers)
3132

tests/benchmarks/test_async_iterable.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import asyncio
2-
from inspect import isawaitable
32

43
from graphql import ExecutionResult, build_schema, execute, parse
4+
from graphql.pyutils import is_awaitable
55

66

77
schema = build_schema("type Query { listField: [String] }")
@@ -18,7 +18,7 @@ async def listField(info_):
1818

1919
async def execute_async() -> ExecutionResult:
2020
result = execute(schema, document, Data())
21-
assert isawaitable(result)
21+
assert is_awaitable(result)
2222
return await result
2323

2424

tests/execution/test_abstract.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
from inspect import isawaitable
21
from typing import Any, NamedTuple, Optional
32

43
from pytest import mark
54

65
from graphql.execution import ExecutionResult, execute, execute_sync
76
from graphql.language import parse
7+
from graphql.pyutils import is_awaitable
88
from graphql.type import (
99
GraphQLBoolean,
1010
GraphQLField,
@@ -43,7 +43,7 @@ async def execute_query(
4343
result = (execute_sync if sync else execute)(
4444
schema, document, root_value
4545
) # type: ignore
46-
if not sync and isawaitable(result):
46+
if not sync and is_awaitable(result):
4747
result = await result
4848
assert isinstance(result, ExecutionResult)
4949
return result

tests/execution/test_sync.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
from inspect import isawaitable
2-
31
from pytest import mark, raises
42

53
from graphql import graphql_sync
64
from graphql.execution import execute, execute_sync
75
from graphql.language import parse
6+
from graphql.pyutils import is_awaitable
87
from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString
98
from graphql.validation import validate
109

@@ -57,7 +56,7 @@ def does_not_return_an_awaitable_if_mutation_fields_are_all_synchronous():
5756
async def returns_an_awaitable_if_any_field_is_asynchronous():
5857
doc = "query Example { syncField, asyncField }"
5958
result = execute(schema, parse(doc), "rootValue")
60-
assert isawaitable(result)
59+
assert is_awaitable(result)
6160
assert await result == (
6261
{"syncField": "rootValue", "asyncField": "rootValue"},
6362
None,

tests/pyutils/test_async_reduce.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from functools import reduce
2-
from inspect import isawaitable
32

43
from pytest import mark
54

6-
from graphql.pyutils import async_reduce
5+
from graphql.pyutils import async_reduce, is_awaitable
76

87

98
def describe_async_reduce():
@@ -25,7 +24,7 @@ def callback(accumulator, current_value):
2524

2625
values = ["bar", "baz"]
2726
result = async_reduce(callback, values, "foo")
28-
assert not isawaitable(result)
27+
assert not is_awaitable(result)
2928
assert result == "foo-bar-baz"
3029

3130
@mark.asyncio
@@ -38,7 +37,7 @@ def callback(accumulator, current_value):
3837

3938
values = ["bar", "baz"]
4039
result = async_reduce(callback, values, async_initial_value())
41-
assert isawaitable(result)
40+
assert is_awaitable(result)
4241
assert await result == "foo-bar-baz"
4342

4443
@mark.asyncio
@@ -48,7 +47,7 @@ async def async_callback(accumulator, current_value):
4847

4948
values = ["bar", "baz"]
5049
result = async_reduce(async_callback, values, "foo")
51-
assert isawaitable(result)
50+
assert is_awaitable(result)
5251
assert await result == "foo-bar-baz"
5352

5453
@mark.asyncio
@@ -60,5 +59,5 @@ async def async_callback(accumulator, current_value):
6059
return accumulator * current_value
6160

6261
result = async_reduce(async_callback, range(6, 9), async_initial_value())
63-
assert isawaitable(result)
62+
assert is_awaitable(result)
6463
assert await result == 42

tests/pyutils/test_simple_pub_sub.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from asyncio import sleep
2-
from inspect import isawaitable
32

43
from pytest import mark, raises
54

6-
from graphql.pyutils import SimplePubSub
5+
from graphql.pyutils import SimplePubSub, is_awaitable
76

87

98
def describe_simple_pub_sub():
@@ -22,9 +21,9 @@ async def subscribe_async_iterator_mock():
2221

2322
# Read ahead
2423
i3 = await iterator.__anext__()
25-
assert isawaitable(i3)
24+
assert is_awaitable(i3)
2625
i4 = await iterator.__anext__()
27-
assert isawaitable(i4)
26+
assert is_awaitable(i4)
2827

2928
# Publish
3029
assert pubsub.emit("Coconut") is True

tests/test_user_registry.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from asyncio import create_task, sleep, wait
88
from collections import defaultdict
99
from enum import Enum
10-
from inspect import isawaitable
1110
from typing import Any, AsyncIterable, Dict, List, NamedTuple, Optional
1211

1312
from pytest import fixture, mark
@@ -29,7 +28,7 @@
2928
parse,
3029
subscribe,
3130
)
32-
from graphql.pyutils import SimplePubSub, SimplePubSubIterator
31+
from graphql.pyutils import SimplePubSub, SimplePubSubIterator, is_awaitable
3332

3433

3534
class User(NamedTuple):
@@ -157,7 +156,7 @@ async def subscribe_user(_root, info, id=None):
157156
"""Subscribe to mutations of a specific user object or all user objects"""
158157
async_iterator = info.context["registry"].event_iterator(id)
159158
async for event in async_iterator:
160-
yield await event if isawaitable(event) else event # pragma: no cover exit
159+
yield await event if is_awaitable(event) else event # pragma: no cover exit
161160

162161

163162
# noinspection PyShadowingBuiltins,PyUnusedLocal

0 commit comments

Comments
 (0)