From 6183cdf21a657e12c4295e30c2aa6c4aca43ff9e Mon Sep 17 00:00:00 2001 From: pushfoo <36696816+pushfoo@users.noreply.github.com> Date: Tue, 14 Oct 2025 19:32:30 -0400 Subject: [PATCH 1/5] Add NoArcadeWindowError and have_window function * Add NoArcadeWindowError subclassing RuntimeError * Make arcade.window_commands.get_window() raise NoArcadeWindowError when no window exists * Add arcade.window_commands.have_window() function * Improve documentation of get_window() function --- arcade/exceptions.py | 10 ++++++++++ arcade/window_commands.py | 27 +++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/arcade/exceptions.py b/arcade/exceptions.py index a3b651823f..72ab9c2e86 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..229991a5be 100644 --- a/arcade/window_commands.py +++ b/arcade/window_commands.py @@ -15,6 +15,7 @@ import pyglet from arcade.types import RGBA255, Color +from arcade.exceptions import NoArcadeWindowError if TYPE_CHECKING: from arcade import Window @@ -25,6 +26,7 @@ __all__ = [ "get_display_size", "get_window", + "have_window", "set_window", "close_window", "run", @@ -54,14 +56,31 @@ def get_display_size(screen_id: int = 0) -> tuple[int, int]: return screen.width, screen.height -def get_window() -> Window: +def have_window() -> bool: + """Returns ``True`` if an Arcade window exists. + + .. tip:: Use this to avoid an :py:class:`~arcade.exceptions.NoArcadeWindowError`. + + + Returns: + Whether a :py:class:`~arcade.Window` exists. """ - Return a handle to the current window. + return _window is None - :return: Handle to the current window. + +def get_window() -> 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:`have_window` + to prevent raising an exception. + + Raises: + :py:class:`~arcade.exceptions.NoArcadeWindowError` when no window exists. """ + # This avoids calling the function above because it may be a hot code path. 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 From 21420a8a771435f7cdc25023d182ea190cf1cfbc Mon Sep 17 00:00:00 2001 From: pushfoo <36696816+pushfoo@users.noreply.github.com> Date: Tue, 14 Oct 2025 19:48:18 -0400 Subject: [PATCH 2/5] Attempt to make ruff happy --- arcade/exceptions.py | 6 +++--- arcade/window_commands.py | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/arcade/exceptions.py b/arcade/exceptions.py index 72ab9c2e86..7ba2c8ed17 100644 --- a/arcade/exceptions.py +++ b/arcade/exceptions.py @@ -24,14 +24,14 @@ _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): """ diff --git a/arcade/window_commands.py b/arcade/window_commands.py index 229991a5be..8af11aa3bd 100644 --- a/arcade/window_commands.py +++ b/arcade/window_commands.py @@ -14,8 +14,8 @@ import pyglet -from arcade.types import RGBA255, Color from arcade.exceptions import NoArcadeWindowError +from arcade.types import RGBA255, Color if TYPE_CHECKING: from arcade import Window @@ -58,9 +58,9 @@ def get_display_size(screen_id: int = 0) -> tuple[int, int]: def have_window() -> bool: """Returns ``True`` if an Arcade window exists. - + .. tip:: Use this to avoid an :py:class:`~arcade.exceptions.NoArcadeWindowError`. - + Returns: Whether a :py:class:`~arcade.Window` exists. @@ -70,7 +70,7 @@ def have_window() -> bool: def get_window() -> 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:`have_window` to prevent raising an exception. @@ -80,7 +80,9 @@ def get_window() -> Window: """ # This avoids calling the function above because it may be a hot code path. if _window is None: - raise NoArcadeWindowError("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 From c190b44bf2f826196ceb41d5caad5c9676ab7eec Mon Sep 17 00:00:00 2001 From: pushfoo <36696816+pushfoo@users.noreply.github.com> Date: Wed, 15 Oct 2025 00:38:56 -0400 Subject: [PATCH 3/5] Remove have_window() since the name / location are controversial --- arcade/window_commands.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/arcade/window_commands.py b/arcade/window_commands.py index 8af11aa3bd..bde6ed9963 100644 --- a/arcade/window_commands.py +++ b/arcade/window_commands.py @@ -26,7 +26,6 @@ __all__ = [ "get_display_size", "get_window", - "have_window", "set_window", "close_window", "run", @@ -56,18 +55,6 @@ def get_display_size(screen_id: int = 0) -> tuple[int, int]: return screen.width, screen.height -def have_window() -> bool: - """Returns ``True`` if an Arcade window exists. - - .. tip:: Use this to avoid an :py:class:`~arcade.exceptions.NoArcadeWindowError`. - - - Returns: - Whether a :py:class:`~arcade.Window` exists. - """ - return _window is None - - def get_window() -> Window: """Return a handle to the current window. @@ -78,7 +65,6 @@ def get_window() -> Window: Raises: :py:class:`~arcade.exceptions.NoArcadeWindowError` when no window exists. """ - # This avoids calling the function above because it may be a hot code path. if _window is None: raise NoArcadeWindowError( "No window is active. It has not been created yet, or it was closed." From a686efefb8416f6a0c63a22df249d26bac86ca9d Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Wed, 15 Oct 2025 10:37:33 -0400 Subject: [PATCH 4/5] Add window_exists function --- arcade/__init__.py | 2 ++ arcade/window_commands.py | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) 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/window_commands.py b/arcade/window_commands.py index bde6ed9963..17a371a24e 100644 --- a/arcade/window_commands.py +++ b/arcade/window_commands.py @@ -27,6 +27,7 @@ "get_display_size", "get_window", "set_window", + "window_exists", "close_window", "run", "exit", @@ -84,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 From e1dfc8d8384b8005de0f8a61685d42c922d0ef1e Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Wed, 15 Oct 2025 16:52:05 -0400 Subject: [PATCH 5/5] Fix doc naming --- arcade/window_commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arcade/window_commands.py b/arcade/window_commands.py index 17a371a24e..13dc5c5533 100644 --- a/arcade/window_commands.py +++ b/arcade/window_commands.py @@ -60,7 +60,7 @@ def get_window() -> 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:`have_window` + handle as a :py:class:`RuntimeError`. Use :py:func:`window_exists` to prevent raising an exception. Raises: