From 55cce46f6b86189f416be49edd7f9d6661646599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niko=20F=C3=B6hr?= Date: Fri, 20 Sep 2024 15:49:59 +0300 Subject: [PATCH] Fix CLI spinner on PyPy on Windows (#396) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes: #274 Amends: #393 The CLI spinner should show ⢎⡡ but PyPy has problems with unicode characters on Windows (printed as ÔóÄÔí░). Therefore, using the old ["|", "/", "-", "\\"] spinner when on PyPy+Windows. --- docs/source/changelog.md | 1 + src/wakepy/__main__.py | 21 ++++++++++++++++++--- tests/unit/test_main.py | 14 +++++++++++++- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/docs/source/changelog.md b/docs/source/changelog.md index 1c35e692..b98b450b 100644 --- a/docs/source/changelog.md +++ b/docs/source/changelog.md @@ -5,6 +5,7 @@ ### ✨ Features - Add support for BSD and other non-Linux Unix-like FOSS desktop systems. All systems running a supported Desktop Environment (currently: KDE, Gnome + other freedesktop compliant DEs) should be supported. ([#379](https://github.com/fohrloop/wakepy/pull/379), [#385](https://github.com/fohrloop/wakepy/pull/385)) +- Add support for PyPy ([#393](https://github.com/fohrloop/wakepy/pull/393) and [#396](https://github.com/fohrloop/wakepy/pull/396)) - When running on an *unknown* platform, do not fail any Methods in the platform check phase anymore, but try to use each Method. This means for example that any system running GNOME that is not Linux (or BSD) could still use wakepy with the [org.gnome.SessionManager](https://wakepy.readthedocs.io/stable/methods-reference.html#org-gnome-sessionmanager) ([#379](https://github.com/fohrloop/wakepy/pull/379)) - 🚨 CLI arguments: Change `-k, --keep-running` to be `-r, --keep-running` and `-p, --presentation` to be `-p, --keep-presenting`; Be more consistent with the naming of the [Modes](#wakepy-modes). The old alternatives are deprecated and will be removed in a future release. ([#356](https://github.com/fohrloop/wakepy/pull/356)) - 🚨 Renamed [`PlatformName`](https://wakepy.readthedocs.io/v0.9.0.post1/api-reference.html#wakepy.core.constants.PlatformName) to [`PlatformType`](https://wakepy.readthedocs.io/v0.10.0/api-reference.html#wakepy.core.constants.PlatformType) and added new types: `ANY`, which means "any platform", `BSD`, meaning "any BSD system" in the future, but currently just FreeBSD / GhostBSD, and `UNIX_LIKE_FOSS`, which means "Unix-like desktop environment, but FOSS". Includes: Linux and BSD. Excludes: Android (mobile), MacOS (non-FOSS), ChromeOS (non-FOSS). Only affects you if you have created custom [Method](https://wakepy.readthedocs.io/v0.9.0.post1/api-reference.html#wakepy.Method) subclasses. ([#379](https://github.com/fohrloop/wakepy/pull/379)) diff --git a/src/wakepy/__main__.py b/src/wakepy/__main__.py index b9dca3ac..61925b1f 100644 --- a/src/wakepy/__main__.py +++ b/src/wakepy/__main__.py @@ -13,6 +13,7 @@ import argparse import itertools +import platform import sys import time import typing @@ -21,7 +22,7 @@ from wakepy import ModeExit from wakepy.core.constants import ModeName from wakepy.core.mode import Mode -from wakepy.core.platform import get_platform_debug_info +from wakepy.core.platform import CURRENT_PLATFORM, get_platform_debug_info, is_windows if typing.TYPE_CHECKING: from typing import List, Tuple @@ -190,7 +191,7 @@ def get_startup_text(mode: ModeName) -> str: from wakepy import __version__ wakepy_text = WAKEPY_TEXT_TEMPLATE.format( - VERSION_STRING=f"{' v.'+__version__: <28}" + VERSION_STRING=f"{' v.'+__version__[:24]: <24}" ) options_txt = WAKEPY_TICKBOXES_TEMPLATE.strip("\n").format( no_auto_suspend="x", @@ -200,7 +201,7 @@ def get_startup_text(mode: ModeName) -> str: def wait_until_keyboardinterrupt() -> None: - spinner_symbols = ["⢎⡰", "⢎⡡", "⢎⡑", "⢎⠱", "⠎⡱", "⢊⡱", "⢌⡱", "⢆⡱"] + spinner_symbols = get_spinner_symbols() try: for spinner_symbol in itertools.cycle(spinner_symbols): # pragma: no branch print("\r " + spinner_symbol + r" [Press Ctrl+C to exit] ", end="") @@ -209,5 +210,19 @@ def wait_until_keyboardinterrupt() -> None: pass +def get_spinner_symbols() -> list[str]: + + if ( + is_windows(CURRENT_PLATFORM) + and platform.python_implementation().lower() == "pypy" + ): + # Windows + PyPy combination does not support unicode well, at least + # yet at version 7.3.17. See: + # https://github.com/pypy/pypy/issues/3890 + # https://github.com/fohrloop/wakepy/issues/274#issuecomment-2363293422 + return ["|", "/", "-", "\\"] + return ["⢎⡰", "⢎⡡", "⢎⡑", "⢎⠱", "⠎⡱", "⢊⡱", "⢌⡱", "⢆⡱"] + + if __name__ == "__main__": main() # pragma: no cover diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index f56082c3..27e5c23d 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -8,6 +8,7 @@ from wakepy import ActivationResult, Method from wakepy.__main__ import ( _get_activation_error_text, + get_spinner_symbols, get_startup_text, handle_activation_error, main, @@ -15,7 +16,7 @@ wait_until_keyboardinterrupt, ) from wakepy.core import PlatformType -from wakepy.core.constants import ModeName +from wakepy.core.constants import IdentifiedPlatformType, ModeName @pytest.fixture @@ -214,3 +215,14 @@ def sys_argv(self): # The patched value for sys.argv. Does not matter here otherwise, but # should be a list of at least two items. return ["", ""] + + +class TestGetSpinnerSymbols: + @patch("wakepy.__main__.CURRENT_PLATFORM", IdentifiedPlatformType.LINUX) + def test_on_linux(self): + assert get_spinner_symbols() == ["⢎⡰", "⢎⡡", "⢎⡑", "⢎⠱", "⠎⡱", "⢊⡱", "⢌⡱", "⢆⡱"] + + @patch("wakepy.__main__.CURRENT_PLATFORM", IdentifiedPlatformType.WINDOWS) + @patch("wakepy.__main__.platform.python_implementation", lambda: "PyPy") + def test_on_windows_pypy(self): + assert get_spinner_symbols() == ["|", "/", "-", "\\"]