Skip to content

Commit 2061511

Browse files
Make .sleep(..) return a coroutine (#18772)
This helps ensure that mypy can catch places where we don't await on it, like in #18763. --------- Co-authored-by: Eric Eastwood <erice@element.io>
1 parent ddbcd85 commit 2061511

7 files changed

Lines changed: 16 additions & 22 deletions

File tree

changelog.d/18772.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Make `Clock.sleep(..)` return a coroutine, so that mypy can catch places where we don't await on it.

synapse/state/v2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class Clock(Protocol):
5252
# This is usually synapse.util.Clock, but it's replaced with a FakeClock in tests.
5353
# We only ever sleep(0) though, so that other async functions can make forward
5454
# progress without waiting for stateres to complete.
55-
def sleep(self, duration_ms: float) -> Awaitable[None]: ...
55+
async def sleep(self, duration_ms: float) -> None: ...
5656

5757

5858
class StateResolutionStore(Protocol):

synapse/util/__init__.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
Any,
2828
Callable,
2929
Dict,
30-
Generator,
3130
Iterator,
3231
Mapping,
3332
Optional,
@@ -42,7 +41,6 @@
4241
from typing_extensions import ParamSpec
4342

4443
from twisted.internet import defer, task
45-
from twisted.internet.defer import Deferred
4644
from twisted.internet.interfaces import IDelayedCall, IReactorTime
4745
from twisted.internet.task import LoopingCall
4846
from twisted.python.failure import Failure
@@ -121,13 +119,11 @@ class Clock:
121119

122120
_reactor: IReactorTime = attr.ib()
123121

124-
@defer.inlineCallbacks
125-
def sleep(self, seconds: float) -> "Generator[Deferred[float], Any, Any]":
122+
async def sleep(self, seconds: float) -> None:
126123
d: defer.Deferred[float] = defer.Deferred()
127124
with context.PreserveLoggingContext():
128125
self._reactor.callLater(seconds, d.callback, seconds)
129-
res = yield d
130-
return res
126+
await d
131127

132128
def time(self) -> float:
133129
"""Returns the current system time in seconds since epoch."""

tests/rest/client/test_transactions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def test_logcontexts_with_async_result(
9090
) -> Generator["defer.Deferred[Any]", object, None]:
9191
@defer.inlineCallbacks
9292
def cb() -> Generator["defer.Deferred[object]", object, Tuple[int, JsonDict]]:
93-
yield Clock(reactor).sleep(0)
93+
yield defer.ensureDeferred(Clock(reactor).sleep(0))
9494
return 1, {}
9595

9696
@defer.inlineCallbacks

tests/server_notices/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ def _check_user_received_server_notice(
131131
break
132132

133133
# Sleep and try again.
134-
self.clock.sleep(0.1)
134+
self.get_success(self.clock.sleep(0.1))
135135
else:
136136
self.fail(
137137
f"Failed to join the server notices room. No 'join' field in sync_body['rooms']: {sync_body['rooms']}"

tests/state/test_v2.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@
6565

6666

6767
class FakeClock:
68-
def sleep(self, msec: float) -> "defer.Deferred[None]":
69-
return defer.succeed(None)
68+
async def sleep(self, msec: float) -> None:
69+
return None
7070

7171

7272
class FakeEvent:

tests/util/test_logcontext.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,18 @@ def test_with_context(self) -> None:
5151
with LoggingContext("test"):
5252
self._check_test_key("test")
5353

54-
@defer.inlineCallbacks
55-
def test_sleep(self) -> Generator["defer.Deferred[object]", object, None]:
54+
async def test_sleep(self) -> None:
5655
clock = Clock(reactor)
5756

58-
@defer.inlineCallbacks
59-
def competing_callback() -> Generator["defer.Deferred[object]", object, None]:
57+
async def competing_callback() -> None:
6058
with LoggingContext("competing"):
61-
yield clock.sleep(0)
59+
await clock.sleep(0)
6260
self._check_test_key("competing")
6361

64-
reactor.callLater(0, competing_callback)
62+
reactor.callLater(0, lambda: defer.ensureDeferred(competing_callback()))
6563

6664
with LoggingContext("one"):
67-
yield clock.sleep(0)
65+
await clock.sleep(0)
6866
self._check_test_key("one")
6967

7068
def _test_run_in_background(self, function: Callable[[], object]) -> defer.Deferred:
@@ -108,9 +106,8 @@ def check_logcontext() -> None:
108106
return d2
109107

110108
def test_run_in_background_with_blocking_fn(self) -> defer.Deferred:
111-
@defer.inlineCallbacks
112-
def blocking_function() -> Generator["defer.Deferred[object]", object, None]:
113-
yield Clock(reactor).sleep(0)
109+
async def blocking_function() -> None:
110+
await Clock(reactor).sleep(0)
114111

115112
return self._test_run_in_background(blocking_function)
116113

@@ -133,7 +130,7 @@ def testfunc() -> defer.Deferred:
133130
def test_run_in_background_with_coroutine(self) -> defer.Deferred:
134131
async def testfunc() -> None:
135132
self._check_test_key("one")
136-
d = Clock(reactor).sleep(0)
133+
d = defer.ensureDeferred(Clock(reactor).sleep(0))
137134
self.assertIs(current_context(), SENTINEL_CONTEXT)
138135
await d
139136
self._check_test_key("one")

0 commit comments

Comments
 (0)