Skip to content

Commit

Permalink
Merge branch 'win-sleep-bug' of github.com:textualize/textual into wi…
Browse files Browse the repository at this point in the history
…n-sleep-bug
  • Loading branch information
rodrigogiraoserrao committed Jun 12, 2023
2 parents 6a1c470 + 38f9bf3 commit 9053fa3
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/textual/_time.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import platform
import asyncio
import platform
from asyncio import sleep as asyncio_sleep
from time import monotonic, perf_counter

Expand Down
14 changes: 13 additions & 1 deletion src/textual/_win_sleep.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
This should only be imported on Windows.
"""

from __future__ import annotations

import asyncio
from time import sleep as time_sleep
from typing import Coroutine
Expand Down Expand Up @@ -31,16 +33,25 @@ async def time_sleep_coro(secs: float):
print("Exception found")

def sleep(secs: float) -> Coroutine[None, None, None]:
"""Wrapper around `time.sleep` to match the signature of the main case below."""
return time_sleep_coro(secs)

else:

async def no_sleep_coro():
"""Creates a coroutine that does nothing for when no sleep is needed."""
pass

def sleep(secs: float) -> Coroutine[None, None, None]:
"""A replacement sleep for Windows.
Note that unlike `time.sleep` this *may* sleep for slightly less than the
specified time. This is generally not an issue for Textual's use case.
In order to create a timer that _can_ be cancelled on Windows, we need to
create a timer and a separate event, and then we wait for either of the two
things. When Textual wants to quit, we set the cancel event.
Args:
secs: Seconds to sleep for.
"""
Expand All @@ -49,7 +60,7 @@ def sleep(secs: float) -> Coroutine[None, None, None]:
sleep_for = max(0, secs - 0.001)
if sleep_for < 0.0005:
# Less than 0.5ms and its not worth doing the sleep
return time_sleep_coro(0)
return no_sleep_coro()

timer = kernel32.CreateWaitableTimerExW(
None,
Expand Down Expand Up @@ -77,6 +88,7 @@ def sleep(secs: float) -> Coroutine[None, None, None]:
return time_sleep_coro(sleep_for)

def cancel_inner():
"""Sets the cancel event so we know we can stop waiting for the timer."""
kernel32.SetEvent(cancel_event)

async def cancel():
Expand Down
1 change: 0 additions & 1 deletion tests/test_win_sleep.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import pytest

from textual._win_sleep import sleep
from textual.app import App

pytestmark = pytest.mark.skipif(
Expand Down

0 comments on commit 9053fa3

Please sign in to comment.