diff --git a/arcade/__init__.py b/arcade/__init__.py index a5152680d6..968e311bf8 100644 --- a/arcade/__init__.py +++ b/arcade/__init__.py @@ -90,6 +90,7 @@ def configure_logging(level: int | None = None): from .window_commands import start_render from .window_commands import unschedule from .window_commands import schedule_once +from .window_commands import window_exists from .sections import Section, SectionManager @@ -359,6 +360,7 @@ def configure_logging(level: int | None = None): "create_text_sprite", "clear_timings", "get_window", + "window_exists", "get_fps", "has_line_of_sight", "load_animated_gif", diff --git a/arcade/exceptions.py b/arcade/exceptions.py index a3b651823f..7ba2c8ed17 100644 --- a/arcade/exceptions.py +++ b/arcade/exceptions.py @@ -7,6 +7,7 @@ from typing import TypeVar __all__ = [ + "NoArcadeWindowError", "OutsideRangeError", "IntOutsideRangeError", "FloatOutsideRangeError", @@ -23,6 +24,15 @@ _CT = TypeVar("_CT") # Comparable type, ie supports the <= operator +class NoArcadeWindowError(RuntimeError): + """No valid Arcade window exists. + + It may be handled as a :py:class:`RuntimeError`. + """ + + ... + + class OutsideRangeError(ValueError): """ Raised when a value is outside and expected range diff --git a/arcade/window_commands.py b/arcade/window_commands.py index 99d2f41c05..13dc5c5533 100644 --- a/arcade/window_commands.py +++ b/arcade/window_commands.py @@ -14,6 +14,7 @@ import pyglet +from arcade.exceptions import NoArcadeWindowError from arcade.types import RGBA255, Color if TYPE_CHECKING: @@ -26,6 +27,7 @@ "get_display_size", "get_window", "set_window", + "window_exists", "close_window", "run", "exit", @@ -55,13 +57,19 @@ def get_display_size(screen_id: int = 0) -> tuple[int, int]: def get_window() -> Window: - """ - Return a handle to the current window. + """Return a handle to the current window. + + If no window exists, it will raise an exception you can + handle as a :py:class:`RuntimeError`. Use :py:func:`window_exists` + to prevent raising an exception. - :return: Handle to the current window. + Raises: + :py:class:`~arcade.exceptions.NoArcadeWindowError` when no window exists. """ if _window is None: - raise RuntimeError("No window is active. It has not been created yet, or it was closed.") + raise NoArcadeWindowError( + "No window is active. It has not been created yet, or it was closed." + ) return _window @@ -77,6 +85,21 @@ def set_window(window: Window | None) -> None: _window = window +def window_exists() -> bool: + """ + Returns True or False based on wether there is currently a Window. + + Returns: + Boolean for if a window exists. + """ + try: + get_window() + except NoArcadeWindowError: + return False + + return True + + def close_window() -> None: """ Closes the current window, and then runs garbage collection. The garbage collection