From 962bdc05db5885f8923585f3abeaeb727d249fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niko=20F=C3=B6hr?= Date: Fri, 13 Sep 2024 10:23:46 +0300 Subject: [PATCH] Change how platform support is defined --- src/wakepy/__main__.py | 1 + src/wakepy/core/__init__.py | 3 +- src/wakepy/core/constants.py | 50 ++++++++-- src/wakepy/core/method.py | 54 +++++------ src/wakepy/core/platform.py | 94 +++++++++++++++++-- src/wakepy/methods/_testing.py | 4 +- src/wakepy/methods/freedesktop.py | 4 +- src/wakepy/methods/gnome.py | 4 +- src/wakepy/methods/macos.py | 4 +- src/wakepy/methods/windows.py | 4 +- tests/unit/test_core/conftest.py | 20 ++-- tests/unit/test_core/test_constants.py | 8 +- .../test_core/test_method/test_activation.py | 41 ++------ .../unit/test_core/test_method/test_method.py | 26 ++++- tests/unit/test_core/test_mode.py | 4 +- tests/unit/test_core/test_platform.py | 72 ++++++++++++-- tests/unit/test_core/test_prioritization.py | 7 +- tests/unit/test_core/testmethods.py | 4 +- tests/unit/test_main.py | 6 +- 19 files changed, 289 insertions(+), 121 deletions(-) diff --git a/src/wakepy/__main__.py b/src/wakepy/__main__.py index df3da857..9828b8a7 100644 --- a/src/wakepy/__main__.py +++ b/src/wakepy/__main__.py @@ -69,6 +69,7 @@ def handle_activation_error(result: ActivationResult) -> None: def _get_activation_error_text(result: ActivationResult) -> str: from wakepy import __version__ + # LATER: This should be improved in https://github.com/fohrloop/wakepy/issues/378 error_text = f""" Wakepy could not activate the "{result.mode_name}" mode. This might occur because of a bug or because your current platform is not yet supported or your system is missing required software. diff --git a/src/wakepy/core/__init__.py b/src/wakepy/core/__init__.py index d8965149..2d023807 100644 --- a/src/wakepy/core/__init__.py +++ b/src/wakepy/core/__init__.py @@ -7,8 +7,9 @@ from .activationresult import ActivationResult as ActivationResult from .activationresult import MethodActivationResult as MethodActivationResult from .constants import BusType as BusType +from .constants import IdentifiedPlatformType as IdentifiedPlatformType from .constants import ModeName as ModeName -from .constants import PlatformName as PlatformName +from .constants import PlatformType as PlatformType from .dbus import DBusAdapter as DBusAdapter from .dbus import DBusAddress as DBusAddress from .dbus import DBusMethod as DBusMethod diff --git a/src/wakepy/core/constants.py b/src/wakepy/core/constants.py index 50563b89..3cbc6526 100644 --- a/src/wakepy/core/constants.py +++ b/src/wakepy/core/constants.py @@ -22,22 +22,56 @@ """ -class PlatformName(StrEnum): - """All the different platforms wakepy knows about. Any platform that is not - detected will be named ``OTHER``.""" +class IdentifiedPlatformType(StrEnum): + """All the different platforms wakepy knows about. Any process will + categorized into exactly one IdentifiedPlatformType type; these are + mutually exclusive options. Any platform that is not detected will be + labeled as ``UNKNOWN``. - WINDOWS = auto() + TODO: Add link to the docs + See also: PlatformType, which you should use with Method subclasses.""" + WINDOWS = auto() LINUX = auto() - MACOS = auto() + FREEBSD = auto() + UNKNOWN = auto() + + +# TODO: Add to docs +# TODO: test that each IdentifiedPlatformType is in PlatformType +class PlatformType(StrEnum): + """Enumeration for supported platform types. Each identified platform can + be categorized to at least one, but potentially many of these. In other + words, each IdentifiedPlatformType maps into one or many PlatformTypes. + + To be used in subclasses of Method in the supported_platforms.""" + + WINDOWS = IdentifiedPlatformType.WINDOWS.value + """Any Windows version from Windows10 onwards.""" + + LINUX = IdentifiedPlatformType.LINUX.value + """Includes any Linux distro. Excludes things like Android & ChromeOS""" + + MACOS = IdentifiedPlatformType.MACOS.value """Mac OS (Darwin)""" - OTHER = auto() - """Anything else""" + FREEBSD = IdentifiedPlatformType.FREEBSD.value + """Also includes GhostBSD""" + + UNKNOWN = IdentifiedPlatformType.UNKNOWN.value + """Any non-identified platform""" + + BSD = auto() + """Any BSD system (Currently just FreeBSD / GhostBSD, but is likely to + change in the future).""" + UNIX_LIKE_FOSS = auto() + """Unix-like desktop environment, but FOSS. Includes: Linux and BSD. + Excludes: Android (mobile), MacOS (non-FOSS), ChromeOS (non-FOSS).""" -PlatformNameValue = Literal["WINDOWS", "LINUX", "MACOS", "OTHER"] + ANY = auto() + """Means any platform.""" class ModeName(StrEnum): diff --git a/src/wakepy/core/method.py b/src/wakepy/core/method.py index 7932e1ec..bce0c2a4 100644 --- a/src/wakepy/core/method.py +++ b/src/wakepy/core/method.py @@ -14,9 +14,9 @@ from typing import Type, cast from .activationresult import MethodActivationResult -from .constants import PlatformName, StageName +from .constants import PlatformType, StageName from .heartbeat import Heartbeat -from .platform import CURRENT_PLATFORM +from .platform import CURRENT_PLATFORM, get_platform_supported from .registry import register_method from .strenum import StrEnum, auto @@ -31,7 +31,7 @@ from wakepy.core import DBusAdapter, DBusMethodCall - from .constants import ModeName, PlatformName + from .constants import ModeName, PlatformType MethodCls = Type["Method"] @@ -69,13 +69,10 @@ class Method(ABC): defines the Mode `foo` (:class:`Mode` classes are themselves not defined or registered anywhere)""" - supported_platforms: Tuple[PlatformName, ...] = ( - PlatformName.LINUX, - PlatformName.WINDOWS, - PlatformName.MACOS, - PlatformName.OTHER, - ) - """Lists the platforms the Method supports. If a platform is not listed in + supported_platforms: Tuple[PlatformType, ...] = (PlatformType.ANY,) + """TODO: UPDATE THIS. + + Lists the platforms the Method supports. If a platform is not listed in ``method.supported_platforms``, the ``method`` is not going to be used on the platform (when used as part of a :class:`Mode`), and the Method activation result will show a fail in the "PLATFORM" stage. @@ -114,6 +111,7 @@ def __init__(self, **kwargs: object) -> None: # waits for https://github.com/fohrloop/wakepy/issues/256 # self.method_kwargs = kwargs + _check_supported_platforms(self.supported_platforms, self.__class__.__name__) def __init_subclass__(cls, **kwargs: object) -> None: register_method(cls) @@ -285,6 +283,22 @@ def is_unnamed(cls) -> bool: return cls.name == unnamed +def _check_supported_platforms( + supported_platforms: Tuple[PlatformType, ...], classname: str +) -> None: + err_supported_platforms = ( + f"The supported_platforms of {classname} must be a tuple of PlatformType!" + ) + + if not isinstance(supported_platforms, tuple): + raise ValueError(err_supported_platforms) + for p in supported_platforms: + if not isinstance(p, PlatformType): + raise ValueError( + err_supported_platforms + f' One item ({p}) is of type "{type(p)}"' + ) + + def activate_method(method: Method) -> Tuple[MethodActivationResult, Heartbeat | None]: """Activates a mode defined by a single Method. @@ -303,7 +317,7 @@ def activate_method(method: Method) -> Tuple[MethodActivationResult, Heartbeat | success=False, method_name=method.name, mode_name=method.mode_name ) - if not get_platform_supported(method, platform=CURRENT_PLATFORM): + if not get_platform_supported(CURRENT_PLATFORM, method.supported_platforms): result.failure_stage = StageName.PLATFORM_SUPPORT return result, None @@ -372,24 +386,6 @@ def deactivate_method(method: Method, heartbeat: Optional[Heartbeat] = None) -> method.dbus_adapter.close_connections() -def get_platform_supported(method: Method, platform: PlatformName) -> bool: - """Checks if method is supported by the platform - - Parameters - ---------- - method: Method - The method which platform support to check. - platform: - The platform to check against. - - Returns - ------- - is_supported: bool - If True, the platform is supported. Otherwise, False. - """ - return platform in method.supported_platforms - - def caniuse_fails(method: Method) -> tuple[bool, str]: """Check if the requirements of a Method are met or not. diff --git a/src/wakepy/core/platform.py b/src/wakepy/core/platform.py index 3e4759f5..50c09c94 100644 --- a/src/wakepy/core/platform.py +++ b/src/wakepy/core/platform.py @@ -1,23 +1,103 @@ +from __future__ import annotations + import platform +import typing import warnings -from .constants import PlatformName +from .constants import IdentifiedPlatformType, PlatformType + +if typing.TYPE_CHECKING: + from typing import Callable, Tuple + + PlatformFunc = Callable[[IdentifiedPlatformType], bool] -def get_current_platform() -> PlatformName: +def get_current_platform() -> IdentifiedPlatformType: # Ref: https://docs.python.org/3/library/platform.html#platform.system system = platform.system() if system == "Windows": - return PlatformName.WINDOWS + return IdentifiedPlatformType.WINDOWS elif system == "Darwin": - return PlatformName.MACOS + return IdentifiedPlatformType.MACOS elif system == "Linux": - return PlatformName.LINUX + return IdentifiedPlatformType.LINUX + elif system == "FreeBSD": + return IdentifiedPlatformType.FREEBSD + # LATER: This should be improved in https://github.com/fohrloop/wakepy/issues/378 warnings.warn( f"Could not detect current platform! platform.system() returned {system}" ) - return PlatformName.OTHER + return IdentifiedPlatformType.UNKNOWN + + +CURRENT_PLATFORM: IdentifiedPlatformType = get_current_platform() + + +def get_platform_supported( + platform: IdentifiedPlatformType, supported_platforms: Tuple[PlatformType, ...] +) -> bool | None: + """Checks if method is supported by the platform + + TODO: Update the docstring. + + Parameters + ---------- + platform: Method + The method which platform support to check. + supported_platforms: + The platform to check against. + + Returns + ------- + is_supported: bool + If platform is supported, returns True. If the support is unknown, + returns None, and if the platform is not supported, returns False. + """ + for supported_platform in supported_platforms: + func = PLATFORM_INFO_FUNCS[supported_platform] + if func(platform) is True: + return True + if is_unknown(platform): + return None + return False + + +def is_windows(current_platform: IdentifiedPlatformType) -> bool: + return current_platform == IdentifiedPlatformType.WINDOWS + + +def is_linux(current_platform: IdentifiedPlatformType) -> bool: + return current_platform == IdentifiedPlatformType.LINUX + + +def is_freebsd(current_platform: IdentifiedPlatformType) -> bool: + return current_platform == IdentifiedPlatformType.FREEBSD + + +def is_macos(current_platform: IdentifiedPlatformType) -> bool: + return current_platform == IdentifiedPlatformType.MACOS + + +def is_bsd(current_platform: IdentifiedPlatformType) -> bool: + return is_freebsd(current_platform) + + +def is_unknown(current_platform: IdentifiedPlatformType) -> bool: + return current_platform == IdentifiedPlatformType.UNKNOWN + + +def is_unix_like_foss(current_platform: IdentifiedPlatformType) -> bool: + return is_bsd(current_platform) or is_linux(current_platform) -CURRENT_PLATFORM = get_current_platform() +PLATFORM_INFO_FUNCS: dict[PlatformType, PlatformFunc] = { + PlatformType.WINDOWS: is_windows, + PlatformType.LINUX: is_linux, + PlatformType.MACOS: is_macos, + PlatformType.FREEBSD: is_freebsd, + PlatformType.UNKNOWN: is_unknown, + PlatformType.BSD: is_bsd, + PlatformType.ANY: lambda _: True, + PlatformType.UNIX_LIKE_FOSS: is_unix_like_foss, +} diff --git a/src/wakepy/methods/_testing.py b/src/wakepy/methods/_testing.py index 2689ca5e..9d022787 100644 --- a/src/wakepy/methods/_testing.py +++ b/src/wakepy/methods/_testing.py @@ -2,7 +2,7 @@ activation success. It is controlled with the WAKEPY_FAKE_SUCCESS environment variable and meant to be used in CI pipelines / tests.""" -from wakepy.core import CURRENT_PLATFORM, Method +from wakepy.core import Method, PlatformType from wakepy.core.constants import WAKEPY_FAKE_SUCCESS @@ -16,7 +16,7 @@ class WakepyFakeSuccess(Method): name = WAKEPY_FAKE_SUCCESS mode_name = "_fake" - supported_platforms = (CURRENT_PLATFORM,) + supported_platforms = (PlatformType.ANY,) def enter_mode(self) -> None: """Does nothing ("succeeds" automatically; Will never raise an diff --git a/src/wakepy/methods/freedesktop.py b/src/wakepy/methods/freedesktop.py index a3803dab..2abbb62e 100644 --- a/src/wakepy/methods/freedesktop.py +++ b/src/wakepy/methods/freedesktop.py @@ -14,7 +14,7 @@ DBusMethodCall, Method, ModeName, - PlatformName, + PlatformType, ) if typing.TYPE_CHECKING: @@ -41,7 +41,7 @@ class FreedesktopInhibitorWithCookieMethod(Method): """Base class for freedesktop.org D-Bus based methods.""" service_dbus_address: DBusAddress - supported_platforms = (PlatformName.LINUX,) + supported_platforms = (PlatformType.LINUX,) def __init__(self, **kwargs: object) -> None: super().__init__(**kwargs) diff --git a/src/wakepy/methods/gnome.py b/src/wakepy/methods/gnome.py index 8ce3fe3a..fd7085a5 100644 --- a/src/wakepy/methods/gnome.py +++ b/src/wakepy/methods/gnome.py @@ -11,7 +11,7 @@ DBusMethodCall, Method, ModeName, - PlatformName, + PlatformType, ) if typing.TYPE_CHECKING: @@ -56,7 +56,7 @@ class _GnomeSessionManager(Method, ABC): params=("inhibit_cookie",), ).of(session_manager) - supported_platforms = (PlatformName.LINUX,) + supported_platforms = (PlatformType.LINUX,) @property @abstractmethod diff --git a/src/wakepy/methods/macos.py b/src/wakepy/methods/macos.py index 63cfbe39..31b3baa0 100644 --- a/src/wakepy/methods/macos.py +++ b/src/wakepy/methods/macos.py @@ -5,7 +5,7 @@ from abc import ABC, abstractmethod from subprocess import PIPE, Popen -from wakepy.core import Method, ModeName, PlatformName +from wakepy.core import Method, ModeName, PlatformType if typing.TYPE_CHECKING: from typing import Optional @@ -18,7 +18,7 @@ class _MacCaffeinate(Method, ABC): Also: https://web.archive.org/web/20140604153141/https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/caffeinate.8.html """ - supported_platforms = (PlatformName.MACOS,) + supported_platforms = (PlatformType.MACOS,) def __init__(self, **kwargs: object) -> None: super().__init__(**kwargs) diff --git a/src/wakepy/methods/windows.py b/src/wakepy/methods/windows.py index caf42bb3..844a06c6 100644 --- a/src/wakepy/methods/windows.py +++ b/src/wakepy/methods/windows.py @@ -9,7 +9,7 @@ from queue import Queue from threading import Event, Thread -from wakepy.core import Method, ModeName, PlatformName +from wakepy.core import Method, ModeName, PlatformType logger = logging.getLogger(__name__) @@ -34,7 +34,7 @@ class WindowsSetThreadExecutionState(Method, ABC): # The SetThreadExecutionState docs say that it supports Windows XP and # above (client) or Windows Server 2003 and above (server) - supported_platforms = (PlatformName.WINDOWS,) + supported_platforms = (PlatformType.WINDOWS,) _wait_timeout = 5 # seconds """timeout for calls like queue.get() and thread.join() which could otherwise block execution indefinitely.""" diff --git a/tests/unit/test_core/conftest.py b/tests/unit/test_core/conftest.py index 0b8c7907..9783d83a 100644 --- a/tests/unit/test_core/conftest.py +++ b/tests/unit/test_core/conftest.py @@ -1,7 +1,7 @@ import pytest from tests.unit.test_core.testmethods import TestMethod -from wakepy.core import DBusAddress, DBusMethod, Method, PlatformName +from wakepy.core import DBusAddress, DBusMethod, Method, PlatformType from wakepy.core.heartbeat import Heartbeat @@ -28,34 +28,34 @@ def provide_methods_different_platforms(monkeypatch, testutils): class WindowsA(TestMethod): name = "WinA" - supported_platforms = (PlatformName.WINDOWS,) + supported_platforms = (PlatformType.WINDOWS,) class WindowsB(TestMethod): name = "WinB" - supported_platforms = (PlatformName.WINDOWS,) + supported_platforms = (PlatformType.WINDOWS,) class WindowsC(TestMethod): name = "WinC" - supported_platforms = (PlatformName.WINDOWS,) + supported_platforms = (PlatformType.WINDOWS,) class LinuxA(TestMethod): name = "LinuxA" - supported_platforms = (PlatformName.LINUX,) + supported_platforms = (PlatformType.LINUX,) class LinuxB(TestMethod): name = "LinuxB" - supported_platforms = (PlatformName.LINUX,) + supported_platforms = (PlatformType.LINUX,) class LinuxC(TestMethod): name = "LinuxC" - supported_platforms = (PlatformName.LINUX,) + supported_platforms = (PlatformType.LINUX,) class MultiPlatformA(TestMethod): name = "multiA" supported_platforms = ( - PlatformName.LINUX, - PlatformName.WINDOWS, - PlatformName.MACOS, + PlatformType.LINUX, + PlatformType.WINDOWS, + PlatformType.MACOS, ) diff --git a/tests/unit/test_core/test_constants.py b/tests/unit/test_core/test_constants.py index 4c7c912d..eb467063 100644 --- a/tests/unit/test_core/test_constants.py +++ b/tests/unit/test_core/test_constants.py @@ -1,9 +1,5 @@ -from wakepy.core import BusType, ModeName, PlatformName -from wakepy.core.constants import BusTypeValue, ModeNameValue, PlatformNameValue - - -def test_platformname(assert_strenum_values): - assert_strenum_values(PlatformName, PlatformNameValue) +from wakepy.core import BusType, ModeName +from wakepy.core.constants import BusTypeValue, ModeNameValue def test_mode_name(assert_strenum_values): diff --git a/tests/unit/test_core/test_method/test_activation.py b/tests/unit/test_core/test_method/test_activation.py index 1c1f4009..3ea03d15 100644 --- a/tests/unit/test_core/test_method/test_activation.py +++ b/tests/unit/test_core/test_method/test_activation.py @@ -17,18 +17,19 @@ combinations_of_test_methods, get_test_method_class, ) -from wakepy.core import Method, MethodActivationResult, PlatformName, get_methods -from wakepy.core.constants import StageName, StageNameValue +from wakepy.core import Method, MethodActivationResult, PlatformType +from wakepy.core.constants import IdentifiedPlatformType, StageName, StageNameValue from wakepy.core.heartbeat import Heartbeat from wakepy.core.method import ( activate_method, caniuse_fails, deactivate_method, - get_platform_supported, try_enter_and_heartbeat, ) from wakepy.core.platform import CURRENT_PLATFORM +P = IdentifiedPlatformType + class TestActivateMethod: """tests for activate_method""" @@ -47,12 +48,13 @@ def test_activate_method_method_without_name(self): activate_method(method) def test_activate_method_method_without_platform_support(self): + unsupported_platform = ( + PlatformType.WINDOWS + if CURRENT_PLATFORM != PlatformType.WINDOWS + else PlatformType.LINUX + ) UnsupportedMethod = get_test_method_class( - supported_platforms=( - PlatformName.WINDOWS - if CURRENT_PLATFORM != PlatformName.WINDOWS - else PlatformName.LINUX - ), + supported_platforms=(unsupported_platform,), ) unsupported_method = UnsupportedMethod() @@ -323,29 +325,6 @@ def test_heartbeat_returns_bad_balue(self): assert heartbeat_call_time is None -class TestPlatformSupported: - """tests for get_platform_supported""" - - @pytest.mark.usefixtures("provide_methods_different_platforms") - def test_get_platform_supported(self): - WindowsA, LinuxA, MultiPlatformA = get_methods(["WinA", "LinuxA", "multiA"]) - - # The windows method is only supported on windows - assert get_platform_supported(WindowsA(), PlatformName.WINDOWS) - assert not get_platform_supported(WindowsA(), PlatformName.LINUX) - assert not get_platform_supported(WindowsA(), PlatformName.MACOS) - - # The linux method is only supported on linux - assert get_platform_supported(LinuxA(), PlatformName.LINUX) - assert not get_platform_supported(LinuxA(), PlatformName.WINDOWS) - assert not get_platform_supported(LinuxA(), PlatformName.MACOS) - - # Case: Method that supports linux, windows and macOS - assert get_platform_supported(MultiPlatformA(), PlatformName.LINUX) - assert get_platform_supported(MultiPlatformA(), PlatformName.WINDOWS) - assert get_platform_supported(MultiPlatformA(), PlatformName.MACOS) - - class TestCanIUseFails: """test caniuse_fails""" diff --git a/tests/unit/test_core/test_method/test_method.py b/tests/unit/test_core/test_method/test_method.py index 67358e7b..b7b99a09 100644 --- a/tests/unit/test_core/test_method/test_method.py +++ b/tests/unit/test_core/test_method/test_method.py @@ -6,12 +6,12 @@ import pytest from tests.unit.test_core.testmethods import TestMethod -from wakepy.core import DBusMethodCall -from wakepy.core.constants import PlatformName +from wakepy.core import DBusMethodCall, PlatformType from wakepy.core.method import ( Method, MethodOutcome, MethodOutcomeValue, + _check_supported_platforms, has_enter, has_exit, has_heartbeat, @@ -122,7 +122,7 @@ def test_method_defaults(): assert m.exit_mode() is None # type: ignore # By default, all platforms are supported - assert set(m.supported_platforms) == set(PlatformName) + assert set(m.supported_platforms) == set((PlatformType.ANY,)) @pytest.mark.usefixtures("provide_methods_a_f") @@ -147,3 +147,23 @@ def test_process_dbus_call(dbus_method: DBusMethod): def test_methodoutcome(assert_strenum_values): assert_strenum_values(MethodOutcome, MethodOutcomeValue) + + +class TestCheckSupportedPlatforms: + def test_wrong_type_of_supported_platforms(self): + + with pytest.raises( + ValueError, + match="The supported_platforms of someclass must be a tuple of PlatformType!", # noqa: E501 + ): + _check_supported_platforms("x", "someclass") # type: ignore + + def test_wrong_type_of_a_single_platform(self): + supported_platforms = (PlatformType.UNIX_LIKE_FOSS, "foo", PlatformType.WINDOWS) + with pytest.raises( + ValueError, + match=re.escape( + "The supported_platforms of someclass must be a tuple of PlatformType! One item (foo) is of type \"\"" # noqa: E501 + ), + ): + _check_supported_platforms(supported_platforms, "someclass") # type: ignore diff --git a/tests/unit/test_core/test_mode.py b/tests/unit/test_core/test_mode.py index b771929b..10d73ec3 100644 --- a/tests/unit/test_core/test_mode.py +++ b/tests/unit/test_core/test_mode.py @@ -10,6 +10,7 @@ from tests.unit.test_core.testmethods import get_test_method_class from wakepy import ActivationError, ActivationResult, Method, Mode +from wakepy.core import PlatformType from wakepy.core.activationresult import MethodActivationResult from wakepy.core.constants import WAKEPY_FAKE_SUCCESS, StageName from wakepy.core.dbus import DBusAdapter @@ -21,7 +22,6 @@ select_methods, should_fake_success, ) -from wakepy.core.platform import CURRENT_PLATFORM from wakepy.core.registry import get_method, get_methods if typing.TYPE_CHECKING: @@ -48,7 +48,7 @@ def methods_abc(monkeypatch, testutils) -> List[Type[Method]]: testutils.empty_method_registry(monkeypatch) class TestMethod(Method): - supported_platforms = (CURRENT_PLATFORM,) + supported_platforms = (PlatformType.ANY,) class MethodA(TestMethod): name = "MethodA" diff --git a/tests/unit/test_core/test_platform.py b/tests/unit/test_core/test_platform.py index 4dd9251e..40d77c73 100644 --- a/tests/unit/test_core/test_platform.py +++ b/tests/unit/test_core/test_platform.py @@ -2,25 +2,85 @@ import pytest -from wakepy.core import PlatformName -from wakepy.core.platform import get_current_platform +from wakepy.core import PlatformType +from wakepy.core.constants import IdentifiedPlatformType +from wakepy.core.platform import get_current_platform, get_platform_supported + +P = IdentifiedPlatformType class TestGetCurrentPlatform: @patch("platform.system", lambda: "Windows") def test_windows(self): - assert get_current_platform() == PlatformName.WINDOWS + assert get_current_platform() == PlatformType.WINDOWS @patch("platform.system", lambda: "Darwin") def test_macos(self): - assert get_current_platform() == PlatformName.MACOS + assert get_current_platform() == PlatformType.MACOS @patch("platform.system", lambda: "Linux") def test_linux(self): - assert get_current_platform() == PlatformName.LINUX + assert get_current_platform() == PlatformType.LINUX + + @patch("platform.system", lambda: "FreeBSD") + def test_bsd(self): + assert get_current_platform() == PlatformType.FREEBSD @patch("platform.system", lambda: "This does not exist") def test_other(self): with pytest.warns(UserWarning, match="Could not detect current platform!"): - assert get_current_platform() == PlatformName.OTHER + assert get_current_platform() == PlatformType.UNKNOWN + + +class TestPlatformSupported: + """tests for get_platform_supported""" + + def test_windows(self): + + # On Windows, anything that supports Windows is supported. + assert get_platform_supported(P.WINDOWS, (PlatformType.WINDOWS,)) is True + assert ( + get_platform_supported( + P.WINDOWS, + (PlatformType.MACOS, PlatformType.WINDOWS, PlatformType.LINUX), + ) + is True + ) + + # If there is no windows in the supported platforms, get False + assert get_platform_supported(P.WINDOWS, (PlatformType.LINUX,)) is False + assert ( + get_platform_supported(P.WINDOWS, (PlatformType.LINUX, PlatformType.BSD)) + is False + ) + # Unless there is ANY, which means anything is supported + assert ( + get_platform_supported( + P.WINDOWS, (PlatformType.LINUX, PlatformType.BSD, PlatformType.ANY) + ) + is True + ) + + def test_unknown(self): + # Unknown platform is always "unknown"; returns None + assert get_platform_supported(P.UNKNOWN, (PlatformType.WINDOWS,)) is None + assert get_platform_supported(P.UNKNOWN, (PlatformType.LINUX,)) is None + # .. unless "ANY" is supported. + assert get_platform_supported(P.UNKNOWN, (PlatformType.ANY,)) is True + + def test_freebsd(self): + + assert get_platform_supported(P.FREEBSD, (PlatformType.WINDOWS,)) is False + assert get_platform_supported(P.FREEBSD, (PlatformType.FREEBSD,)) is True + # FreeBSD is BSD + assert get_platform_supported(P.FREEBSD, (PlatformType.BSD,)) is True + # FreeBSD is unix like + assert get_platform_supported(P.FREEBSD, (PlatformType.UNIX_LIKE_FOSS,)) is True + + def test_linux(self): + + assert get_platform_supported(P.LINUX, (PlatformType.WINDOWS,)) is False + assert get_platform_supported(P.LINUX, (PlatformType.LINUX,)) is True + # Linux is unix like + assert get_platform_supported(P.LINUX, (PlatformType.UNIX_LIKE_FOSS,)) is True diff --git a/tests/unit/test_core/test_prioritization.py b/tests/unit/test_core/test_prioritization.py index e05a4e36..6c37b208 100644 --- a/tests/unit/test_core/test_prioritization.py +++ b/tests/unit/test_core/test_prioritization.py @@ -5,7 +5,7 @@ import pytest -from wakepy.core import PlatformName +from wakepy.core import PlatformType from wakepy.core.constants import WAKEPY_FAKE_SUCCESS from wakepy.core.prioritization import ( _check_methods_priority, @@ -25,7 +25,7 @@ def set_current_platform_to_linux(monkeypatch): monkeypatch.setattr( - "wakepy.core.prioritization.CURRENT_PLATFORM", PlatformName.LINUX + "wakepy.core.prioritization.CURRENT_PLATFORM", PlatformType.LINUX ) @@ -33,7 +33,8 @@ def set_current_platform_to_linux(monkeypatch): def set_current_platform_to_windows(monkeypatch): monkeypatch.setattr( - "wakepy.core.prioritization.CURRENT_PLATFORM", PlatformName.WINDOWS + "wakepy.core.prioritization.CURRENT_PLATFORM", + PlatformType.WINDOWS, ) diff --git a/tests/unit/test_core/testmethods.py b/tests/unit/test_core/testmethods.py index 71817f8e..8f6469ec 100644 --- a/tests/unit/test_core/testmethods.py +++ b/tests/unit/test_core/testmethods.py @@ -38,7 +38,7 @@ from collections import Counter from typing import Iterable, Type -from wakepy.core import CURRENT_PLATFORM +from wakepy.core import PlatformType from wakepy.core.method import Method @@ -82,7 +82,7 @@ def get_test_method_class( enter_mode=METHOD_MISSING, heartbeat=METHOD_MISSING, exit_mode=METHOD_MISSING, - supported_platforms=(CURRENT_PLATFORM,), + supported_platforms=(PlatformType.ANY,), ) -> Type[Method]: """Get a test Method class with the .caniuse(), .enter_mode(), .heartbeat() and .exit_mode() methods defined as wanted. All methods can either be: diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index 8d844147..f56082c3 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -14,7 +14,7 @@ parse_arguments, wait_until_keyboardinterrupt, ) -from wakepy.core import CURRENT_PLATFORM +from wakepy.core import PlatformType from wakepy.core.constants import ModeName @@ -36,7 +36,7 @@ class WorkingMethod(Method): name = "method1" mode_name = mode_name_working - supported_platforms = (CURRENT_PLATFORM,) + supported_platforms = (PlatformType.ANY,) def enter_mode(self) -> None: return @@ -52,7 +52,7 @@ class BrokenMethod(Method): name = "method2_broken" mode_name = mode_name_broken - supported_platforms = (CURRENT_PLATFORM,) + supported_platforms = (PlatformType.ANY,) def enter_mode(self) -> None: raise RuntimeError("foo")